summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/filesystems/ocfs2.txt3
-rw-r--r--MAINTAINERS15
-rw-r--r--arch/arm/mach-omap2/clock24xx.h4
-rw-r--r--arch/parisc/include/asm/module.h6
-rw-r--r--arch/parisc/kernel/module.c216
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c1
-rw-r--r--arch/s390/hypfs/inode.c1
-rw-r--r--arch/sparc/Kconfig57
-rw-r--r--arch/sparc/configs/sparc64_defconfig105
-rw-r--r--arch/sparc/include/asm/Kbuild20
-rw-r--r--arch/sparc/include/asm/byteorder.h12
-rw-r--r--arch/sparc/include/asm/ipcbuf.h38
-rw-r--r--arch/sparc/include/asm/ipcbuf_32.h31
-rw-r--r--arch/sparc/include/asm/ipcbuf_64.h28
-rw-r--r--arch/sparc/include/asm/jsflash.h2
-rw-r--r--arch/sparc/include/asm/openprom.h277
-rw-r--r--arch/sparc/include/asm/openprom_32.h255
-rw-r--r--arch/sparc/include/asm/openprom_64.h280
-rw-r--r--arch/sparc/include/asm/posix_types.h157
-rw-r--r--arch/sparc/include/asm/posix_types_32.h118
-rw-r--r--arch/sparc/include/asm/posix_types_64.h122
-rw-r--r--arch/sparc/include/asm/processor_32.h2
-rw-r--r--arch/sparc/include/asm/ptrace.h448
-rw-r--r--arch/sparc/include/asm/ptrace_32.h186
-rw-r--r--arch/sparc/include/asm/ptrace_64.h356
-rw-r--r--arch/sparc/include/asm/reg.h8
-rw-r--r--arch/sparc/include/asm/reg_32.h79
-rw-r--r--arch/sparc/include/asm/reg_64.h56
-rw-r--r--arch/sparc/include/asm/sigcontext.h102
-rw-r--r--arch/sparc/include/asm/sigcontext_32.h62
-rw-r--r--arch/sparc/include/asm/sigcontext_64.h87
-rw-r--r--arch/sparc/include/asm/siginfo.h43
-rw-r--r--arch/sparc/include/asm/siginfo_32.h17
-rw-r--r--arch/sparc/include/asm/siginfo_64.h32
-rw-r--r--arch/sparc/include/asm/signal.h212
-rw-r--r--arch/sparc/include/asm/signal_32.h207
-rw-r--r--arch/sparc/include/asm/signal_64.h194
-rw-r--r--arch/sparc/include/asm/smp_32.h3
-rw-r--r--arch/sparc/include/asm/stat.h111
-rw-r--r--arch/sparc/include/asm/stat_32.h76
-rw-r--r--arch/sparc/include/asm/stat_64.h47
-rw-r--r--arch/sparc/include/asm/thread_info_32.h2
-rw-r--r--arch/sparc/include/asm/traps.h11
-rw-r--r--arch/sparc/kernel/irq_32.c2
-rw-r--r--arch/sparc/kernel/kgdb_32.c12
-rw-r--r--arch/sparc/kernel/muldiv.c8
-rw-r--r--arch/sparc/kernel/pci_psycho.c5
-rw-r--r--arch/sparc/kernel/process_32.c16
-rw-r--r--arch/sparc/kernel/prom_common.c14
-rw-r--r--arch/sparc/kernel/signal_32.c6
-rw-r--r--arch/sparc/kernel/traps_32.c4
-rw-r--r--arch/sparc/kernel/unaligned_32.c12
-rw-r--r--arch/sparc/kernel/windows.c6
-rw-r--r--arch/um/Makefile25
-rw-r--r--arch/um/include/asm/system.h14
-rw-r--r--arch/x86/Kconfig.cpu2
-rw-r--r--arch/x86/kernel/cpu/cpufreq/p4-clockmod.c6
-rw-r--r--arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c51
-rw-r--r--arch/x86/kernel/cpu/cpufreq/speedstep-lib.c9
-rw-r--r--arch/x86/kernel/pci-swiotlb_64.c2
-rw-r--r--drivers/cpufreq/cpufreq.c55
-rw-r--r--drivers/hid/Kconfig70
-rw-r--r--drivers/hid/Makefile5
-rw-r--r--drivers/hid/hid-bright.c71
-rw-r--r--drivers/hid/hid-core.c120
-rw-r--r--drivers/hid/hid-dell.c76
-rw-r--r--drivers/hid/hid-dummy.c6
-rw-r--r--drivers/hid/hid-gaff.c185
-rw-r--r--drivers/hid/hid-ids.h21
-rw-r--r--drivers/hid/hid-lg.c7
-rw-r--r--drivers/hid/hid-ntrig.c82
-rw-r--r--drivers/hid/hid-sony.c2
-rw-r--r--drivers/hid/hid-topseed.c77
-rw-r--r--drivers/hid/hidraw.c32
-rw-r--r--drivers/hid/usbhid/Kconfig2
-rw-r--r--drivers/hid/usbhid/hid-core.c34
-rw-r--r--drivers/hid/usbhid/hid-quirks.c1
-rw-r--r--drivers/hid/usbhid/hiddev.c135
-rw-r--r--drivers/hid/usbhid/usbhid.h10
-rw-r--r--drivers/i2c/busses/i2c-omap.c420
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c185
-rw-r--r--drivers/i2c/chips/Kconfig23
-rw-r--r--drivers/i2c/chips/Makefile2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_fs.c3
-rw-r--r--drivers/isdn/capi/capidrv.c4
-rw-r--r--drivers/isdn/capi/capifs.c2
-rw-r--r--drivers/md/Makefile5
-rw-r--r--drivers/md/dm-crypt.c6
-rw-r--r--drivers/md/dm-delay.c6
-rw-r--r--drivers/md/dm-exception-store.c749
-rw-r--r--drivers/md/dm-exception-store.h148
-rw-r--r--drivers/md/dm-ioctl.c16
-rw-r--r--drivers/md/dm-linear.c6
-rw-r--r--drivers/md/dm-log.c40
-rw-r--r--drivers/md/dm-mpath.c14
-rw-r--r--drivers/md/dm-raid1.c24
-rw-r--r--drivers/md/dm-snap-persistent.c704
-rw-r--r--drivers/md/dm-snap-transient.c98
-rw-r--r--drivers/md/dm-snap.c48
-rw-r--r--drivers/md/dm-snap.h129
-rw-r--r--drivers/md/dm-stripe.c4
-rw-r--r--drivers/md/dm-sysfs.c99
-rw-r--r--drivers/md/dm-table.c47
-rw-r--r--drivers/md/dm-target.c15
-rw-r--r--drivers/md/dm-zero.c5
-rw-r--r--drivers/md/dm.c101
-rw-r--r--drivers/md/dm.h10
-rw-r--r--drivers/message/i2o/exec-osm.c2
-rw-r--r--drivers/message/i2o/i2o_config.c2
-rw-r--r--drivers/message/i2o/iop.c2
-rw-r--r--drivers/message/i2o/pci.c2
-rw-r--r--drivers/mfd/Kconfig66
-rw-r--r--drivers/mfd/Makefile7
-rw-r--r--drivers/mfd/da903x.c16
-rw-r--r--drivers/mfd/dm355evm_msp.c420
-rw-r--r--drivers/mfd/menelaus.c (renamed from drivers/i2c/chips/menelaus.c)0
-rw-r--r--drivers/mfd/mfd-core.c1
-rw-r--r--drivers/mfd/tps65010.c (renamed from drivers/i2c/chips/tps65010.c)0
-rw-r--r--drivers/mfd/twl4030-core.c472
-rw-r--r--drivers/mfd/twl4030-irq.c30
-rw-r--r--drivers/mfd/wm8350-core.c266
-rw-r--r--drivers/mfd/wm8350-i2c.c4
-rw-r--r--drivers/mfd/wm8350-regmap.c2100
-rw-r--r--drivers/mfd/wm8400-core.c31
-rw-r--r--drivers/misc/ibmasm/ibmasmfs.c2
-rw-r--r--drivers/net/acenic.c117
-rw-r--r--drivers/net/acenic.h4
-rw-r--r--drivers/net/e100.c268
-rw-r--r--drivers/net/ehea/ehea.h3
-rw-r--r--drivers/net/ehea/ehea_main.c2
-rw-r--r--drivers/net/enc28j60.c4
-rw-r--r--drivers/net/igb/igb_main.c4
-rw-r--r--drivers/net/myri10ge/myri10ge.c6
-rw-r--r--drivers/net/qlge/qlge.h57
-rw-r--r--drivers/net/qlge/qlge_dbg.c13
-rw-r--r--drivers/net/qlge/qlge_ethtool.c8
-rw-r--r--drivers/net/qlge/qlge_main.c116
-rw-r--r--drivers/net/starfire.c54
-rw-r--r--drivers/net/starfire_firmware.h346
-rw-r--r--drivers/net/starfire_firmware.pl31
-rw-r--r--drivers/net/tg3.c792
-rw-r--r--drivers/net/tg3.h4
-rw-r--r--drivers/net/tun.c2
-rw-r--r--drivers/oprofile/oprofilefs.c3
-rw-r--r--drivers/power/Kconfig14
-rw-r--r--drivers/power/Makefile2
-rw-r--r--drivers/power/da9030_battery.c600
-rw-r--r--drivers/power/power_supply_sysfs.c2
-rw-r--r--drivers/power/wm8350_power.c532
-rw-r--r--drivers/regulator/wm8350-regulator.c7
-rw-r--r--drivers/rtc/Kconfig6
-rw-r--r--drivers/rtc/interface.c54
-rw-r--r--drivers/rtc/rtc-dev.c51
-rw-r--r--drivers/s390/net/qeth_core.h1
-rw-r--r--drivers/s390/net/qeth_core_main.c57
-rw-r--r--drivers/s390/net/qeth_l2_main.c8
-rw-r--r--drivers/s390/net/qeth_l3_main.c26
-rw-r--r--drivers/usb/core/inode.c1
-rw-r--r--drivers/usb/gadget/file_storage.c18
-rw-r--r--drivers/usb/gadget/inode.c1
-rw-r--r--drivers/video/via/viafbdev.c248
-rw-r--r--firmware/Makefile11
-rw-r--r--firmware/WHENCE49
-rw-r--r--firmware/acenic/tg1.bin.ihex4573
-rw-r--r--firmware/acenic/tg2.bin.ihex4844
-rw-r--r--firmware/adaptec/starfire_rx.bin.ihex53
-rw-r--r--firmware/adaptec/starfire_tx.bin.ihex53
-rw-r--r--firmware/tigon/tg3.bin.ihex175
-rw-r--r--firmware/tigon/tg3_tso.bin.ihex446
-rw-r--r--firmware/tigon/tg3_tso5.bin.ihex252
-rw-r--r--fs/Kconfig18
-rw-r--r--fs/Makefile1
-rw-r--r--fs/affs/file.c2
-rw-r--r--fs/affs/inode.c3
-rw-r--r--fs/afs/write.c2
-rw-r--r--fs/autofs/inode.c2
-rw-r--r--fs/autofs4/inode.c4
-rw-r--r--fs/binfmt_misc.c3
-rw-r--r--fs/buffer.c4
-rw-r--r--fs/cifs/file.c2
-rw-r--r--fs/cifs/inode.c2
-rw-r--r--fs/coda/file.c12
-rw-r--r--fs/configfs/inode.c3
-rw-r--r--fs/cramfs/inode.c2
-rw-r--r--fs/debugfs/inode.c3
-rw-r--r--fs/devpts/inode.c4
-rw-r--r--fs/dlm/ast.c56
-rw-r--r--fs/dlm/ast.h4
-rw-r--r--fs/dlm/debug_fs.c310
-rw-r--r--fs/dlm/dir.c18
-rw-r--r--fs/dlm/dlm_internal.h4
-rw-r--r--fs/dlm/lock.c31
-rw-r--r--fs/dlm/lowcomms.c8
-rw-r--r--fs/dlm/memory.c6
-rw-r--r--fs/dlm/midcomms.c2
-rw-r--r--fs/dlm/netlink.c1
-rw-r--r--fs/dlm/user.c4
-rw-r--r--fs/dlm/user.h2
-rw-r--r--fs/dquot.c436
-rw-r--r--fs/ecryptfs/file.c15
-rw-r--r--fs/ecryptfs/inode.c3
-rw-r--r--fs/ecryptfs/mmap.c2
-rw-r--r--fs/exec.c5
-rw-r--r--fs/ext3/inode.c2
-rw-r--r--fs/ext3/namei.c3
-rw-r--r--fs/ext3/super.c16
-rw-r--r--fs/ext4/ext4_sb.h6
-rw-r--r--fs/ext4/inode.c4
-rw-r--r--fs/ext4/namei.c3
-rw-r--r--fs/ext4/super.c15
-rw-r--r--fs/filesystems.c23
-rw-r--r--fs/fuse/file.c4
-rw-r--r--fs/gfs2/Makefile2
-rw-r--r--fs/gfs2/acl.c2
-rw-r--r--fs/gfs2/bmap.c77
-rw-r--r--fs/gfs2/bmap.h34
-rw-r--r--fs/gfs2/daemon.c136
-rw-r--r--fs/gfs2/daemon.h17
-rw-r--r--fs/gfs2/dir.c62
-rw-r--r--fs/gfs2/dir.h1
-rw-r--r--fs/gfs2/eattr.c40
-rw-r--r--fs/gfs2/glock.c303
-rw-r--r--fs/gfs2/glock.h2
-rw-r--r--fs/gfs2/glops.c56
-rw-r--r--fs/gfs2/incore.h55
-rw-r--r--fs/gfs2/inode.c53
-rw-r--r--fs/gfs2/inode.h13
-rw-r--r--fs/gfs2/locking/dlm/mount.c12
-rw-r--r--fs/gfs2/locking/dlm/sysfs.c16
-rw-r--r--fs/gfs2/main.c15
-rw-r--r--fs/gfs2/mount.c29
-rw-r--r--fs/gfs2/ops_address.c34
-rw-r--r--fs/gfs2/ops_dentry.c2
-rw-r--r--fs/gfs2/ops_dentry.h17
-rw-r--r--fs/gfs2/ops_export.c5
-rw-r--r--fs/gfs2/ops_file.c22
-rw-r--r--fs/gfs2/ops_fstype.c125
-rw-r--r--fs/gfs2/ops_fstype.h19
-rw-r--r--fs/gfs2/ops_inode.c75
-rw-r--r--fs/gfs2/ops_inode.h25
-rw-r--r--fs/gfs2/ops_super.c149
-rw-r--r--fs/gfs2/ops_super.h17
-rw-r--r--fs/gfs2/quota.c113
-rw-r--r--fs/gfs2/quota.h24
-rw-r--r--fs/gfs2/recovery.c48
-rw-r--r--fs/gfs2/recovery.h14
-rw-r--r--fs/gfs2/rgrp.c58
-rw-r--r--fs/gfs2/super.c246
-rw-r--r--fs/gfs2/super.h13
-rw-r--r--fs/gfs2/sys.c66
-rw-r--r--fs/gfs2/sys.h4
-rw-r--r--fs/gfs2/util.c1
-rw-r--r--fs/gfs2/util.h1
-rw-r--r--fs/hostfs/hostfs_kern.c2
-rw-r--r--fs/hugetlbfs/inode.c1
-rw-r--r--fs/inode.c2
-rw-r--r--fs/ioctl.c44
-rw-r--r--fs/isofs/inode.c6
-rw-r--r--fs/jbd2/commit.c9
-rw-r--r--fs/jbd2/journal.c19
-rw-r--r--fs/jbd2/transaction.c47
-rw-r--r--fs/jffs2/file.c2
-rw-r--r--fs/jfs/jfs_imap.c10
-rw-r--r--fs/libfs.c7
-rw-r--r--fs/namei.c45
-rw-r--r--fs/nfs/file.c2
-rw-r--r--fs/nfsd/vfs.c43
-rw-r--r--fs/notify/inotify/inotify_user.c2
-rw-r--r--fs/ntfs/inode.c3
-rw-r--r--fs/ocfs2/Makefile7
-rw-r--r--fs/ocfs2/acl.c479
-rw-r--r--fs/ocfs2/acl.h58
-rw-r--r--fs/ocfs2/alloc.c710
-rw-r--r--fs/ocfs2/alloc.h30
-rw-r--r--fs/ocfs2/aops.c59
-rw-r--r--fs/ocfs2/blockcheck.c477
-rw-r--r--fs/ocfs2/blockcheck.h82
-rw-r--r--fs/ocfs2/buffer_head_io.c32
-rw-r--r--fs/ocfs2/buffer_head_io.h27
-rw-r--r--fs/ocfs2/cluster/masklog.c1
-rw-r--r--fs/ocfs2/cluster/masklog.h1
-rw-r--r--fs/ocfs2/dir.c399
-rw-r--r--fs/ocfs2/dir.h2
-rw-r--r--fs/ocfs2/dlm/dlmast.c52
-rw-r--r--fs/ocfs2/dlm/dlmcommon.h3
-rw-r--r--fs/ocfs2/dlm/dlmdebug.c53
-rw-r--r--fs/ocfs2/dlm/dlmdomain.c1
-rw-r--r--fs/ocfs2/dlm/dlmfs.c2
-rw-r--r--fs/ocfs2/dlm/dlmmaster.c42
-rw-r--r--fs/ocfs2/dlm/dlmthread.c3
-rw-r--r--fs/ocfs2/dlmglue.c168
-rw-r--r--fs/ocfs2/dlmglue.h19
-rw-r--r--fs/ocfs2/extent_map.c96
-rw-r--r--fs/ocfs2/extent_map.h24
-rw-r--r--fs/ocfs2/file.c209
-rw-r--r--fs/ocfs2/file.h3
-rw-r--r--fs/ocfs2/inode.c175
-rw-r--r--fs/ocfs2/inode.h18
-rw-r--r--fs/ocfs2/journal.c364
-rw-r--r--fs/ocfs2/journal.h128
-rw-r--r--fs/ocfs2/localalloc.c26
-rw-r--r--fs/ocfs2/namei.c318
-rw-r--r--fs/ocfs2/ocfs2.h46
-rw-r--r--fs/ocfs2/ocfs2_fs.h213
-rw-r--r--fs/ocfs2/ocfs2_jbd_compat.h82
-rw-r--r--fs/ocfs2/ocfs2_lockid.h5
-rw-r--r--fs/ocfs2/quota.h119
-rw-r--r--fs/ocfs2/quota_global.c1025
-rw-r--r--fs/ocfs2/quota_local.c1253
-rw-r--r--fs/ocfs2/resize.c76
-rw-r--r--fs/ocfs2/slot_map.c4
-rw-r--r--fs/ocfs2/suballoc.c363
-rw-r--r--fs/ocfs2/suballoc.h18
-rw-r--r--fs/ocfs2/super.c328
-rw-r--r--fs/ocfs2/symlink.c2
-rw-r--r--fs/ocfs2/xattr.c2984
-rw-r--r--fs/ocfs2/xattr.h45
-rw-r--r--fs/omfs/inode.c1
-rw-r--r--fs/open.c2
-rw-r--r--fs/openpromfs/inode.c3
-rw-r--r--fs/pipe.c7
-rw-r--r--fs/proc/base.c4
-rw-r--r--fs/proc/proc_sysctl.c1
-rw-r--r--fs/quota.c11
-rw-r--r--fs/quota_tree.c645
-rw-r--r--fs/quota_tree.h25
-rw-r--r--fs/quota_v1.c28
-rw-r--r--fs/quota_v2.c631
-rw-r--r--fs/quotaio_v1.h (renamed from include/linux/quotaio_v1.h)0
-rw-r--r--fs/quotaio_v2.h (renamed from include/linux/quotaio_v2.h)33
-rw-r--r--fs/ramfs/inode.c1
-rw-r--r--fs/read_write.c13
-rw-r--r--fs/reiserfs/inode.c15
-rw-r--r--fs/reiserfs/super.c10
-rw-r--r--fs/romfs/inode.c1
-rw-r--r--fs/smbfs/file.c2
-rw-r--r--fs/stat.c2
-rw-r--r--fs/sync.c48
-rw-r--r--fs/sysfs/inode.c3
-rw-r--r--fs/ubifs/file.c9
-rw-r--r--fs/xattr.c2
-rw-r--r--include/linux/Kbuild4
-rw-r--r--include/linux/audit.h98
-rw-r--r--include/linux/blockgroup_lock.h7
-rw-r--r--include/linux/cpufreq.h1
-rw-r--r--include/linux/device-mapper.h28
-rw-r--r--include/linux/dma_remapping.h8
-rw-r--r--include/linux/dqblk_qtree.h56
-rw-r--r--include/linux/dqblk_v1.h7
-rw-r--r--include/linux/dqblk_v2.h22
-rw-r--r--include/linux/ext2_fs_sb.h6
-rw-r--r--include/linux/ext3_fs_sb.h6
-rw-r--r--include/linux/fs.h10
-rw-r--r--include/linux/hid.h16
-rw-r--r--include/linux/hidraw.h2
-rw-r--r--include/linux/i2c/dm355evm_msp.h79
-rw-r--r--include/linux/i2c/twl4030.h81
-rw-r--r--include/linux/jbd2.h32
-rw-r--r--include/linux/journal-head.h8
-rw-r--r--include/linux/mfd/da903x.h44
-rw-r--r--include/linux/mfd/wm8350/comparator.h8
-rw-r--r--include/linux/mfd/wm8350/core.h52
-rw-r--r--include/linux/mfd/wm8350/pmic.h4
-rw-r--r--include/linux/mfd/wm8350/supply.h25
-rw-r--r--include/linux/moduleloader.h3
-rw-r--r--include/linux/netdevice.h16
-rw-r--r--include/linux/pagemap.h3
-rw-r--r--include/linux/power_supply.h1
-rw-r--r--include/linux/quota.h108
-rw-r--r--include/linux/quotaops.h96
-rw-r--r--include/linux/radix-tree.h2
-rw-r--r--include/linux/rtc.h8
-rw-r--r--include/linux/spi/spi.h2
-rw-r--r--include/linux/stop_machine.h22
-rw-r--r--include/linux/syscalls.h2
-rw-r--r--include/net/ndisc.h4
-rw-r--r--init/Kconfig6
-rw-r--r--ipc/mqueue.c98
-rw-r--r--ipc/sem.c2
-rw-r--r--ipc/shm.c4
-rw-r--r--ipc/util.c18
-rw-r--r--kernel/audit.h5
-rw-r--r--kernel/audit_tree.c3
-rw-r--r--kernel/auditfilter.c325
-rw-r--r--kernel/auditsc.c739
-rw-r--r--kernel/capability.c4
-rw-r--r--kernel/cgroup.c7
-rw-r--r--kernel/cpu.c6
-rw-r--r--kernel/module.c59
-rw-r--r--kernel/stop_machine.c55
-rw-r--r--lib/swiotlb.c3
-rw-r--r--mm/filemap.c15
-rw-r--r--mm/memory.c4
-rw-r--r--mm/mmap.c2
-rw-r--r--mm/mprotect.c2
-rw-r--r--mm/mremap.c2
-rw-r--r--mm/msync.c2
-rw-r--r--mm/nommu.c2
-rw-r--r--mm/vmalloc.c5
-rw-r--r--net/can/bcm.c208
-rw-r--r--net/core/dev.c93
-rw-r--r--net/core/skbuff.c15
-rw-r--r--net/dcb/dcbnl.c14
-rw-r--r--net/dccp/Kconfig4
-rw-r--r--net/dccp/Makefile15
-rw-r--r--net/dccp/ackvec.h49
-rw-r--r--net/dccp/ccid.c254
-rw-r--r--net/dccp/ccid.h14
-rw-r--r--net/dccp/ccids/Kconfig79
-rw-r--r--net/dccp/ccids/Makefile9
-rw-r--r--net/dccp/ccids/ccid2.c22
-rw-r--r--net/dccp/ccids/ccid3.c23
-rw-r--r--net/dccp/ccids/lib/Makefile3
-rw-r--r--net/dccp/ccids/lib/loss_interval.c3
-rw-r--r--net/dccp/ccids/lib/packet_history.c9
-rw-r--r--net/dccp/ccids/lib/tfrc.c19
-rw-r--r--net/dccp/ccids/lib/tfrc.h11
-rw-r--r--net/dccp/ccids/lib/tfrc_equation.c4
-rw-r--r--net/dccp/dccp.h2
-rw-r--r--net/dccp/feat.c6
-rw-r--r--net/dccp/input.c2
-rw-r--r--net/dccp/proto.c7
-rw-r--r--net/ipv4/tcp.c9
-rw-r--r--net/ipv6/ipv6_sockglue.c2
-rw-r--r--net/ipv6/route.c52
-rw-r--r--net/iucv/af_iucv.c28
-rw-r--r--net/iucv/iucv.c18
-rw-r--r--net/rfkill/rfkill.c4
-rw-r--r--net/sched/cls_u32.c3
-rw-r--r--net/socket.c13
-rw-r--r--net/sunrpc/rpc_pipe.c2
-rw-r--r--security/commoncap.c6
-rw-r--r--security/inode.c3
-rw-r--r--security/selinux/selinuxfs.c2
-rw-r--r--security/selinux/ss/services.c26
-rw-r--r--security/smack/smack_lsm.c6
-rw-r--r--sound/pci/hda/patch_conexant.c114
-rw-r--r--sound/pci/hda/patch_realtek.c3
-rw-r--r--sound/pci/ice1712/ice1724.c2
-rw-r--r--sound/soc/codecs/twl4030.c377
-rw-r--r--sound/soc/codecs/twl4030.h7
-rw-r--r--sound/soc/davinci/davinci-sffsdr.c4
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.c4
-rw-r--r--sound/soc/soc-core.c46
-rw-r--r--sound/soc/soc-dapm.c10
-rw-r--r--sound/usb/caiaq/caiaq-device.c4
-rw-r--r--sound/usb/usbaudio.c8
-rw-r--r--sound/usb/usbmidi.c39
-rw-r--r--sound/usb/usbmixer.c5
-rw-r--r--sound/usb/usx2y/us122l.c4
-rw-r--r--sound/usb/usx2y/usbusx2y.c4
451 files changed, 32709 insertions, 12153 deletions
diff --git a/Documentation/filesystems/ocfs2.txt b/Documentation/filesystems/ocfs2.txt
index 67310fbbb7d..c2a0871280a 100644
--- a/Documentation/filesystems/ocfs2.txt
+++ b/Documentation/filesystems/ocfs2.txt
@@ -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.
diff --git a/MAINTAINERS b/MAINTAINERS
index befacf07729..141aff67bd6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4015,10 +4015,12 @@ L: alsa-devel@alsa-project.org (subscribers-only)
W: http://alsa-project.org/main/index.php/ASoC
S: Supported
-SPARC (sparc32)
-P: William L. Irwin
-M: wli@holomorphy.com
+SPARC + UltraSPARC (sparc/sparc64)
+P: David S. Miller
+M: davem@davemloft.net
L: sparclinux@vger.kernel.org
+T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6.git
+T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-next-2.6.git
S: Maintained
SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER
@@ -4302,13 +4304,6 @@ M: dushistov@mail.ru
L: linux-kernel@vger.kernel.org
S: Maintained
-UltraSPARC (sparc64)
-P: David S. Miller
-M: davem@davemloft.net
-L: sparclinux@vger.kernel.org
-T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6.git
-S: Maintained
-
ULTRA-WIDEBAND (UWB) SUBSYSTEM:
P: David Vrabel
M: david.vrabel@csr.com
diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h
index ff6cd14d254..ad6d98d177c 100644
--- a/arch/arm/mach-omap2/clock24xx.h
+++ b/arch/arm/mach-omap2/clock24xx.h
@@ -2321,7 +2321,7 @@ static struct clk i2c2_fck = {
};
static struct clk i2chs2_fck = {
- .name = "i2chs_fck",
+ .name = "i2c_fck",
.id = 2,
.parent = &func_96m_ck,
.flags = CLOCK_IN_OMAP243X,
@@ -2354,7 +2354,7 @@ static struct clk i2c1_fck = {
};
static struct clk i2chs1_fck = {
- .name = "i2chs_fck",
+ .name = "i2c_fck",
.id = 1,
.parent = &func_96m_ck,
.flags = CLOCK_IN_OMAP243X,
diff --git a/arch/parisc/include/asm/module.h b/arch/parisc/include/asm/module.h
index c2cb49e934c..1f4123427ea 100644
--- a/arch/parisc/include/asm/module.h
+++ b/arch/parisc/include/asm/module.h
@@ -23,8 +23,10 @@ struct mod_arch_specific
{
unsigned long got_offset, got_count, got_max;
unsigned long fdesc_offset, fdesc_count, fdesc_max;
- unsigned long stub_offset, stub_count, stub_max;
- unsigned long init_stub_offset, init_stub_count, init_stub_max;
+ struct {
+ unsigned long stub_offset;
+ unsigned int stub_entries;
+ } *section;
int unwind_section;
struct unwind_table *unwind;
};
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c
index 44138c3e6ea..9013243cecc 100644
--- a/arch/parisc/kernel/module.c
+++ b/arch/parisc/kernel/module.c
@@ -6,6 +6,7 @@
*
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
* Copyright (C) 2003 Randolph Chung <tausq at debian . org>
+ * Copyright (C) 2008 Helge Deller <deller@gmx.de>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -24,6 +25,19 @@
*
*
* Notes:
+ * - PLT stub handling
+ * On 32bit (and sometimes 64bit) and with big kernel modules like xfs or
+ * ipv6 the relocation types R_PARISC_PCREL17F and R_PARISC_PCREL22F may
+ * fail to reach their PLT stub if we only create one big stub array for
+ * all sections at the beginning of the core or init section.
+ * Instead we now insert individual PLT stub entries directly in front of
+ * of the code sections where the stubs are actually called.
+ * This reduces the distance between the PCREL location and the stub entry
+ * so that the relocations can be fulfilled.
+ * While calculating the final layout of the kernel module in memory, the
+ * kernel module loader calls arch_mod_section_prepend() to request the
+ * to be reserved amount of memory in front of each individual section.
+ *
* - SEGREL32 handling
* We are not doing SEGREL32 handling correctly. According to the ABI, we
* should do a value offset, like this:
@@ -58,9 +72,13 @@
#define DEBUGP(fmt...)
#endif
+#define RELOC_REACHABLE(val, bits) \
+ (( ( !((val) & (1<<((bits)-1))) && ((val)>>(bits)) != 0 ) || \
+ ( ((val) & (1<<((bits)-1))) && ((val)>>(bits)) != (((__typeof__(val))(~0))>>((bits)+2)))) ? \
+ 0 : 1)
+
#define CHECK_RELOC(val, bits) \
- if ( ( !((val) & (1<<((bits)-1))) && ((val)>>(bits)) != 0 ) || \
- ( ((val) & (1<<((bits)-1))) && ((val)>>(bits)) != (((__typeof__(val))(~0))>>((bits)+2)))) { \
+ if (!RELOC_REACHABLE(val, bits)) { \
printk(KERN_ERR "module %s relocation of symbol %s is out of range (0x%lx in %d bits)\n", \
me->name, strtab + sym->st_name, (unsigned long)val, bits); \
return -ENOEXEC; \
@@ -92,13 +110,6 @@ static inline int in_local(struct module *me, void *loc)
return in_init(me, loc) || in_core(me, loc);
}
-static inline int in_local_section(struct module *me, void *loc, void *dot)
-{
- return (in_init(me, loc) && in_init(me, dot)) ||
- (in_core(me, loc) && in_core(me, dot));
-}
-
-
#ifndef CONFIG_64BIT
struct got_entry {
Elf32_Addr addr;
@@ -258,23 +269,42 @@ static inline unsigned long count_stubs(const Elf_Rela *rela, unsigned long n)
/* Free memory returned from module_alloc */
void module_free(struct module *mod, void *module_region)
{
+ kfree(mod->arch.section);
+ mod->arch.section = NULL;
+
vfree(module_region);
/* FIXME: If module_region == mod->init_region, trim exception
table entries. */
}
+/* Additional bytes needed in front of individual sections */
+unsigned int arch_mod_section_prepend(struct module *mod,
+ unsigned int section)
+{
+ /* size needed for all stubs of this section (including
+ * one additional for correct alignment of the stubs) */
+ return (mod->arch.section[section].stub_entries + 1)
+ * sizeof(struct stub_entry);
+}
+
#define CONST
int module_frob_arch_sections(CONST Elf_Ehdr *hdr,
CONST Elf_Shdr *sechdrs,
CONST char *secstrings,
struct module *me)
{
- unsigned long gots = 0, fdescs = 0, stubs = 0, init_stubs = 0;
+ unsigned long gots = 0, fdescs = 0, len;
unsigned int i;
+ len = hdr->e_shnum * sizeof(me->arch.section[0]);
+ me->arch.section = kzalloc(len, GFP_KERNEL);
+ if (!me->arch.section)
+ return -ENOMEM;
+
for (i = 1; i < hdr->e_shnum; i++) {
- const Elf_Rela *rels = (void *)hdr + sechdrs[i].sh_offset;
+ const Elf_Rela *rels = (void *)sechdrs[i].sh_addr;
unsigned long nrels = sechdrs[i].sh_size / sizeof(*rels);
+ unsigned int count, s;
if (strncmp(secstrings + sechdrs[i].sh_name,
".PARISC.unwind", 14) == 0)
@@ -290,11 +320,23 @@ int module_frob_arch_sections(CONST Elf_Ehdr *hdr,
*/
gots += count_gots(rels, nrels);
fdescs += count_fdescs(rels, nrels);
- if(strncmp(secstrings + sechdrs[i].sh_name,
- ".rela.init", 10) == 0)
- init_stubs += count_stubs(rels, nrels);
- else
- stubs += count_stubs(rels, nrels);
+
+ /* XXX: By sorting the relocs and finding duplicate entries
+ * we could reduce the number of necessary stubs and save
+ * some memory. */
+ count = count_stubs(rels, nrels);
+ if (!count)
+ continue;
+
+ /* so we need relocation stubs. reserve necessary memory. */
+ /* sh_info gives the section for which we need to add stubs. */
+ s = sechdrs[i].sh_info;
+
+ /* each code section should only have one relocation section */
+ WARN_ON(me->arch.section[s].stub_entries);
+
+ /* store number of stubs we need for this section */
+ me->arch.section[s].stub_entries += count;
}
/* align things a bit */
@@ -306,18 +348,8 @@ int module_frob_arch_sections(CONST Elf_Ehdr *hdr,
me->arch.fdesc_offset = me->core_size;
me->core_size += fdescs * sizeof(Elf_Fdesc);
- me->core_size = ALIGN(me->core_size, 16);
- me->arch.stub_offset = me->core_size;
- me->core_size += stubs * sizeof(struct stub_entry);
-
- me->init_size = ALIGN(me->init_size, 16);
- me->arch.init_stub_offset = me->init_size;
- me->init_size += init_stubs * sizeof(struct stub_entry);
-
me->arch.got_max = gots;
me->arch.fdesc_max = fdescs;
- me->arch.stub_max = stubs;
- me->arch.init_stub_max = init_stubs;
return 0;
}
@@ -380,23 +412,27 @@ enum elf_stub_type {
};
static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
- enum elf_stub_type stub_type, int init_section)
+ enum elf_stub_type stub_type, Elf_Addr loc0, unsigned int targetsec)
{
- unsigned long i;
struct stub_entry *stub;
- if(init_section) {
- i = me->arch.init_stub_count++;
- BUG_ON(me->arch.init_stub_count > me->arch.init_stub_max);
- stub = me->module_init + me->arch.init_stub_offset +
- i * sizeof(struct stub_entry);
- } else {
- i = me->arch.stub_count++;
- BUG_ON(me->arch.stub_count > me->arch.stub_max);
- stub = me->module_core + me->arch.stub_offset +
- i * sizeof(struct stub_entry);
+ /* initialize stub_offset to point in front of the section */
+ if (!me->arch.section[targetsec].stub_offset) {
+ loc0 -= (me->arch.section[targetsec].stub_entries + 1) *
+ sizeof(struct stub_entry);
+ /* get correct alignment for the stubs */
+ loc0 = ALIGN(loc0, sizeof(struct stub_entry));
+ me->arch.section[targetsec].stub_offset = loc0;
}
+ /* get address of stub entry */
+ stub = (void *) me->arch.section[targetsec].stub_offset;
+ me->arch.section[targetsec].stub_offset += sizeof(struct stub_entry);
+
+ /* do not write outside available stub area */
+ BUG_ON(0 == me->arch.section[targetsec].stub_entries--);
+
+
#ifndef CONFIG_64BIT
/* for 32-bit the stub looks like this:
* ldil L'XXX,%r1
@@ -489,15 +525,19 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
Elf32_Addr val;
Elf32_Sword addend;
Elf32_Addr dot;
+ Elf_Addr loc0;
+ unsigned int targetsec = sechdrs[relsec].sh_info;
//unsigned long dp = (unsigned long)$global$;
register unsigned long dp asm ("r27");
DEBUGP("Applying relocate section %u to %u\n", relsec,
- sechdrs[relsec].sh_info);
+ targetsec);
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
/* This is where to make the change */
- loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ loc = (void *)sechdrs[targetsec].sh_addr
+ rel[i].r_offset;
+ /* This is the start of the target section */
+ loc0 = sechdrs[targetsec].sh_addr;
/* This is the symbol it is referring to */
sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+ ELF32_R_SYM(rel[i].r_info);
@@ -569,19 +609,32 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
break;
case R_PARISC_PCREL17F:
/* 17-bit PC relative address */
- val = get_stub(me, val, addend, ELF_STUB_GOT, in_init(me, loc));
+ /* calculate direct call offset */
+ val += addend;
val = (val - dot - 8)/4;
- CHECK_RELOC(val, 17)
+ if (!RELOC_REACHABLE(val, 17)) {
+ /* direct distance too far, create
+ * stub entry instead */
+ val = get_stub(me, sym->st_value, addend,
+ ELF_STUB_DIRECT, loc0, targetsec);
+ val = (val - dot - 8)/4;
+ CHECK_RELOC(val, 17);
+ }
*loc = (*loc & ~0x1f1ffd) | reassemble_17(val);
break;
case R_PARISC_PCREL22F:
/* 22-bit PC relative address; only defined for pa20 */
- val = get_stub(me, val, addend, ELF_STUB_GOT, in_init(me, loc));
- DEBUGP("STUB FOR %s loc %lx+%lx at %lx\n",
- strtab + sym->st_name, (unsigned long)loc, addend,
- val)
+ /* calculate direct call offset */
+ val += addend;
val = (val - dot - 8)/4;
- CHECK_RELOC(val, 22);
+ if (!RELOC_REACHABLE(val, 22)) {
+ /* direct distance too far, create
+ * stub entry instead */
+ val = get_stub(me, sym->st_value, addend,
+ ELF_STUB_DIRECT, loc0, targetsec);
+ val = (val - dot - 8)/4;
+ CHECK_RELOC(val, 22);
+ }
*loc = (*loc & ~0x3ff1ffd) | reassemble_22(val);
break;
@@ -610,13 +663,17 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
Elf64_Addr val;
Elf64_Sxword addend;
Elf64_Addr dot;
+ Elf_Addr loc0;
+ unsigned int targetsec = sechdrs[relsec].sh_info;
DEBUGP("Applying relocate section %u to %u\n", relsec,
- sechdrs[relsec].sh_info);
+ targetsec);
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
/* This is where to make the change */
- loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ loc = (void *)sechdrs[targetsec].sh_addr
+ rel[i].r_offset;
+ /* This is the start of the target section */
+ loc0 = sechdrs[targetsec].sh_addr;
/* This is the symbol it is referring to */
sym = (Elf64_Sym *)sechdrs[symindex].sh_addr
+ ELF64_R_SYM(rel[i].r_info);
@@ -672,42 +729,40 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
DEBUGP("PCREL22F Symbol %s loc %p val %lx\n",
strtab + sym->st_name,
loc, val);
+ val += addend;
/* can we reach it locally? */
- if(!in_local_section(me, (void *)val, (void *)dot)) {
-
- if (in_local(me, (void *)val))
- /* this is the case where the
- * symbol is local to the
- * module, but in a different
- * section, so stub the jump
- * in case it's more than 22
- * bits away */
- val = get_stub(me, val, addend, ELF_STUB_DIRECT,
- in_init(me, loc));
- else if (strncmp(strtab + sym->st_name, "$$", 2)
+ if (in_local(me, (void *)val)) {
+ /* this is the case where the symbol is local
+ * to the module, but in a different section,
+ * so stub the jump in case it's more than 22
+ * bits away */
+ val = (val - dot - 8)/4;
+ if (!RELOC_REACHABLE(val, 22)) {
+ /* direct distance too far, create
+ * stub entry instead */
+ val = get_stub(me, sym->st_value,
+ addend, ELF_STUB_DIRECT,
+ loc0, targetsec);
+ } else {
+ /* Ok, we can reach it directly. */
+ val = sym->st_value;
+ val += addend;
+ }
+ } else {
+ val = sym->st_value;
+ if (strncmp(strtab + sym->st_name, "$$", 2)
== 0)
val = get_stub(me, val, addend, ELF_STUB_MILLI,
- in_init(me, loc));
+ loc0, targetsec);
else
val = get_stub(me, val, addend, ELF_STUB_GOT,
- in_init(me, loc));
+ loc0, targetsec);
}
DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n",
strtab + sym->st_name, loc, sym->st_value,
addend, val);
- /* FIXME: local symbols work as long as the
- * core and init pieces aren't separated too
- * far. If this is ever broken, you will trip
- * the check below. The way to fix it would
- * be to generate local stubs to go between init
- * and core */
- if((Elf64_Sxword)(val - dot - 8) > 0x800000 -1 ||
- (Elf64_Sxword)(val - dot - 8) < -0x800000) {
- printk(KERN_ERR "Module %s, symbol %s is out of range for PCREL22F relocation\n",
- me->name, strtab + sym->st_name);
- return -ENOEXEC;
- }
val = (val - dot - 8)/4;
+ CHECK_RELOC(val, 22);
*loc = (*loc & ~0x3ff1ffd) | reassemble_22(val);
break;
case R_PARISC_DIR64:
@@ -794,12 +849,8 @@ int module_finalize(const Elf_Ehdr *hdr,
addr = (u32 *)entry->addr;
printk("INSNS: %x %x %x %x\n",
addr[0], addr[1], addr[2], addr[3]);
- printk("stubs used %ld, stubs max %ld\n"
- "init_stubs used %ld, init stubs max %ld\n"
- "got entries used %ld, gots max %ld\n"
+ printk("got entries used %ld, gots max %ld\n"
"fdescs used %ld, fdescs max %ld\n",
- me->arch.stub_count, me->arch.stub_max,
- me->arch.init_stub_count, me->arch.init_stub_max,
me->arch.got_count, me->arch.got_max,
me->arch.fdesc_count, me->arch.fdesc_max);
#endif
@@ -829,7 +880,10 @@ int module_finalize(const Elf_Ehdr *hdr,
me->name, me->arch.got_count, MAX_GOTS);
return -EINVAL;
}
-
+
+ kfree(me->arch.section);
+ me->arch.section = NULL;
+
/* no symbol table */
if(symhdr == NULL)
return 0;
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 6296bfd9cb0..e309ef70a53 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -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;
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index 9d4f8e6c080..5a805df216b 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -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;
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 0a94d9c9cde..de58c02633b 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -4,6 +4,17 @@
mainmenu "Linux/SPARC Kernel Configuration"
+config 64BIT
+ bool "64-bit kernel" if ARCH = "sparc"
+ default ARCH = "sparc64"
+ help
+ SPARC is a family of RISC microprocessors designed and marketed by
+ Sun Microsystems, incorporated. They are very widely found in Sun
+ workstations and clones.
+
+ Say yes to build a 64-bit kernel - formerly known as sparc64
+ Say no to build a 32-bit kernel - formerly known as sparc
+
config SPARC
bool
default y
@@ -15,22 +26,11 @@ config SPARC
select RTC_CLASS
select RTC_DRV_M48T59
-# Identify this as a Sparc32 build
config SPARC32
- bool
- default y if ARCH = "sparc"
- help
- SPARC is a family of RISC microprocessors designed and marketed by
- Sun Microsystems, incorporated. They are very widely found in Sun
- workstations and clones. This port covers the original 32-bit SPARC;
- it is old and stable and usually considered one of the "big three"
- along with the Intel and Alpha ports. The UltraLinux project
- maintains both the SPARC32 and SPARC64 ports; its web page is
- available at <http://www.ultralinux.org/>.
+ def_bool !64BIT
config SPARC64
- bool
- default y if ARCH = "sparc64"
+ def_bool 64BIT
select ARCH_SUPPORTS_MSI
select HAVE_FUNCTION_TRACER
select HAVE_KRETPROBES
@@ -53,9 +53,6 @@ config BITS
default 32 if SPARC32
default 64 if SPARC64
-config 64BIT
- def_bool y if SPARC64
-
config GENERIC_TIME
bool
default y if SPARC64
@@ -188,14 +185,6 @@ config ARCH_MAY_HAVE_PC_FDC
bool
default y
-config ARCH_HAS_ILOG2_U32
- bool
- default n
-
-config ARCH_HAS_ILOG2_U64
- bool
- default n
-
config EMULATED_CMPXCHG
bool
default y if SPARC32
@@ -442,26 +431,6 @@ config SERIAL_CONSOLE
endmenu
menu "Bus options (PCI etc.)"
-config ISA
- bool
- help
- ISA is found on Espresso only and is not supported currently.
-
-config ISAPNP
- bool
- help
- ISAPNP is not supported
-
-config EISA
- bool
- help
- EISA is not supported.
-
-config MCA
- bool
- help
- MCA is not supported.
-
config SBUS
bool
default y
diff --git a/arch/sparc/configs/sparc64_defconfig b/arch/sparc/configs/sparc64_defconfig
index 05d19a3e590..cde19ae78f5 100644
--- a/arch/sparc/configs/sparc64_defconfig
+++ b/arch/sparc/configs/sparc64_defconfig
@@ -1,27 +1,27 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc4
-# Mon Nov 10 12:35:09 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 2 18:14:26 2009
#
CONFIG_SPARC=y
CONFIG_SPARC64=y
+CONFIG_ARCH_DEFCONFIG="arch/sparc/configs/sparc64_defconfig"
+CONFIG_BITS=64
+CONFIG_64BIT=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_CLOCKEVENTS=y
-CONFIG_64BIT=y
-CONFIG_MMU=y
CONFIG_IOMMU_HELPER=y
CONFIG_QUICKLIST=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_AUDIT_ARCH=y
CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_MMU=y
CONFIG_ARCH_NO_VIRT_TO_BUS=y
CONFIG_OF=y
-CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -86,6 +86,7 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
# CONFIG_MARKERS is not set
CONFIG_OPROFILE=m
CONFIG_HAVE_OPROFILE=y
@@ -127,34 +128,40 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
# Processor type and features
#
-CONFIG_SPARC64_PAGE_SIZE_8KB=y
-# CONFIG_SPARC64_PAGE_SIZE_64KB is not set
-CONFIG_SECCOMP=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=64
CONFIG_HZ_100=y
# CONFIG_HZ_250 is not set
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=100
CONFIG_SCHED_HRTICK=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_SPARC64_SMP=y
+CONFIG_SPARC64_PAGE_SIZE_8KB=y
+# CONFIG_SPARC64_PAGE_SIZE_64KB is not set
+CONFIG_SECCOMP=y
CONFIG_HOTPLUG_CPU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
-CONFIG_SMP=y
-CONFIG_NR_CPUS=64
# CONFIG_CPU_FREQ is not set
CONFIG_US3_MC=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HUGETLB_PAGE_SIZE_4MB=y
# CONFIG_HUGETLB_PAGE_SIZE_512K is not set
# CONFIG_HUGETLB_PAGE_SIZE_64K is not set
@@ -183,10 +190,18 @@ CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=1
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options (PCI etc.)
+#
CONFIG_SBUS=y
CONFIG_SBUSCHAR=y
-CONFIG_SUN_AUXIO=y
-CONFIG_SUN_IO=y
CONFIG_SUN_LDOMS=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
@@ -195,7 +210,9 @@ CONFIG_ARCH_SUPPORTS_MSI=y
CONFIG_PCI_MSI=y
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCCARD is not set
CONFIG_SUN_OPENPROMFS=m
+CONFIG_SPARC64_PCI=y
#
# Executable file formats
@@ -207,17 +224,13 @@ CONFIG_COMPAT_BINFMT_ELF=y
CONFIG_BINFMT_MISC=m
CONFIG_COMPAT=y
CONFIG_SYSVIPC_COMPAT=y
-CONFIG_SCHED_SMT=y
-CONFIG_SCHED_MC=y
-# CONFIG_PREEMPT_NONE is not set
-CONFIG_PREEMPT_VOLUNTARY=y
-# CONFIG_PREEMPT is not set
-# CONFIG_CMDLINE_BOOL is not set
CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NET_NS is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -314,6 +327,7 @@ CONFIG_VLAN_8021Q=m
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -330,8 +344,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -378,8 +392,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
@@ -387,6 +403,7 @@ CONFIG_IDE=y
# Please see Documentation/ide/ide.txt for help/info on IDE drives
#
CONFIG_IDE_TIMINGS=y
+CONFIG_IDE_ATAPI=y
# CONFIG_BLK_DEV_IDE_SATA is not set
CONFIG_IDE_GD=y
CONFIG_IDE_GD_ATA=y
@@ -394,7 +411,6 @@ CONFIG_IDE_GD_ATA=y
CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -477,6 +493,7 @@ CONFIG_SCSI_FC_ATTRS=y
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -490,6 +507,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
@@ -564,6 +583,9 @@ CONFIG_PHYLIB=m
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=m
@@ -590,7 +612,6 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -600,6 +621,7 @@ CONFIG_NET_PCI=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
@@ -629,6 +651,7 @@ CONFIG_BNX2=m
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -778,6 +801,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=m
@@ -870,6 +894,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
# CONFIG_SENSORS_ATXP1 is not set
@@ -919,11 +944,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -1071,6 +1096,7 @@ CONFIG_SND_MIXER_OSS=m
CONFIG_SND_PCM_OSS=m
CONFIG_SND_PCM_OSS_PLUGINS=y
CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_HRTIMER is not set
# CONFIG_SND_DYNAMIC_MINORS is not set
CONFIG_SND_SUPPORT_OLD_API=y
CONFIG_SND_VERBOSE_PROCFS=y
@@ -1242,11 +1268,11 @@ CONFIG_USB_UHCI_HCD=m
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_DEBUG is not set
@@ -1337,6 +1363,7 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -1365,7 +1392,6 @@ CONFIG_RTC_DRV_STARFIRE=y
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Misc Linux/SPARC drivers
@@ -1544,6 +1570,7 @@ CONFIG_SCHEDSTATS=y
# CONFIG_LOCK_STAT is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
@@ -1552,6 +1579,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1560,8 +1588,12 @@ CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_LKDTM is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_NOP_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
#
# Tracers
@@ -1571,7 +1603,9 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
@@ -1600,11 +1634,16 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 89c260aab45..deeb0fba802 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -1,21 +1,6 @@
# User exported sparc header files
include include/asm-generic/Kbuild.asm
-header-y += ipcbuf_32.h
-header-y += ipcbuf_64.h
-header-y += posix_types_32.h
-header-y += posix_types_64.h
-header-y += ptrace_32.h
-header-y += ptrace_64.h
-header-y += sigcontext_32.h
-header-y += sigcontext_64.h
-header-y += siginfo_32.h
-header-y += siginfo_64.h
-header-y += signal_32.h
-header-y += signal_64.h
-header-y += stat_32.h
-header-y += stat_64.h
-
header-y += apc.h
header-y += asi.h
header-y += display7seg.h
@@ -23,16 +8,11 @@ header-y += envctrl.h
header-y += fbio.h
header-y += jsflash.h
header-y += openprom.h
-header-y += openprom_32.h
-header-y += openprom_64.h
header-y += openpromio.h
header-y += perfctr.h
header-y += psrcompat.h
header-y += psr.h
header-y += pstate.h
-header-y += reg.h
-header-y += reg_32.h
-header-y += reg_64.h
header-y += traps.h
header-y += uctx.h
header-y += utrap.h
diff --git a/arch/sparc/include/asm/byteorder.h b/arch/sparc/include/asm/byteorder.h
index 5a70f137f1f..738414b2655 100644
--- a/arch/sparc/include/asm/byteorder.h
+++ b/arch/sparc/include/asm/byteorder.h
@@ -1,16 +1,12 @@
#ifndef _SPARC_BYTEORDER_H
#define _SPARC_BYTEORDER_H
-#include <asm/types.h>
+#include <linux/types.h>
#include <asm/asi.h>
#define __BIG_ENDIAN
-#ifdef CONFIG_SPARC32
-#define __SWAB_64_THRU_32__
-#endif
-
-#ifdef CONFIG_SPARC64
+#if defined(__sparc__) && defined(__arch64__)
static inline __u16 __arch_swab16p(const __u16 *addr)
{
__u16 ret;
@@ -44,7 +40,9 @@ static inline __u64 __arch_swab64p(const __u64 *addr)
}
#define __arch_swab64p __arch_swab64p
-#endif /* CONFIG_SPARC64 */
+#else
+#define __SWAB_64_THRU_32__
+#endif /* defined(__sparc__) && defined(__arch64__) */
#include <linux/byteorder.h>
diff --git a/arch/sparc/include/asm/ipcbuf.h b/arch/sparc/include/asm/ipcbuf.h
index 17d6ef7b23a..66013b4fe10 100644
--- a/arch/sparc/include/asm/ipcbuf.h
+++ b/arch/sparc/include/asm/ipcbuf.h
@@ -1,8 +1,32 @@
-#ifndef ___ASM_SPARC_IPCBUF_H
-#define ___ASM_SPARC_IPCBUF_H
-#if defined(__sparc__) && defined(__arch64__)
-#include <asm/ipcbuf_64.h>
-#else
-#include <asm/ipcbuf_32.h>
-#endif
+#ifndef __SPARC_IPCBUF_H
+#define __SPARC_IPCBUF_H
+
+/*
+ * The ipc64_perm structure for sparc/sparc64 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 32-bit seq
+ * - on sparc for 32 bit mode (it is 32 bit on sparc64)
+ * - 2 miscellaneous 64-bit values
+ */
+
+struct ipc64_perm
+{
+ __kernel_key_t key;
+ __kernel_uid_t uid;
+ __kernel_gid_t gid;
+ __kernel_uid_t cuid;
+ __kernel_gid_t cgid;
+#ifndef __arch64__
+ unsigned short __pad0;
#endif
+ __kernel_mode_t mode;
+ unsigned short __pad1;
+ unsigned short seq;
+ unsigned long long __unused1;
+ unsigned long long __unused2;
+};
+
+#endif /* __SPARC_IPCBUF_H */
diff --git a/arch/sparc/include/asm/ipcbuf_32.h b/arch/sparc/include/asm/ipcbuf_32.h
deleted file mode 100644
index 6387209518f..00000000000
--- a/arch/sparc/include/asm/ipcbuf_32.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef _SPARC_IPCBUF_H
-#define _SPARC_IPCBUF_H
-
-/*
- * The ipc64_perm structure for sparc architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 32-bit mode
- * - 32-bit seq
- * - 2 miscellaneous 64-bit values (so that this structure matches
- * sparc64 ipc64_perm)
- */
-
-struct ipc64_perm
-{
- __kernel_key_t key;
- __kernel_uid32_t uid;
- __kernel_gid32_t gid;
- __kernel_uid32_t cuid;
- __kernel_gid32_t cgid;
- unsigned short __pad1;
- __kernel_mode_t mode;
- unsigned short __pad2;
- unsigned short seq;
- unsigned long long __unused1;
- unsigned long long __unused2;
-};
-
-#endif /* _SPARC_IPCBUF_H */
diff --git a/arch/sparc/include/asm/ipcbuf_64.h b/arch/sparc/include/asm/ipcbuf_64.h
deleted file mode 100644
index a44b855b98d..00000000000
--- a/arch/sparc/include/asm/ipcbuf_64.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef _SPARC64_IPCBUF_H
-#define _SPARC64_IPCBUF_H
-
-/*
- * The ipc64_perm structure for sparc64 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 32-bit seq
- * - 2 miscellaneous 64-bit values
- */
-
-struct ipc64_perm
-{
- __kernel_key_t key;
- __kernel_uid_t uid;
- __kernel_gid_t gid;
- __kernel_uid_t cuid;
- __kernel_gid_t cgid;
- __kernel_mode_t mode;
- unsigned short __pad1;
- unsigned short seq;
- unsigned long __unused1;
- unsigned long __unused2;
-};
-
-#endif /* _SPARC64_IPCBUF_H */
diff --git a/arch/sparc/include/asm/jsflash.h b/arch/sparc/include/asm/jsflash.h
index 3457f29bd73..0717d9e39d2 100644
--- a/arch/sparc/include/asm/jsflash.h
+++ b/arch/sparc/include/asm/jsflash.h
@@ -8,7 +8,7 @@
#define _SPARC_JSFLASH_H
#ifndef _SPARC_TYPES_H
-#include <asm/types.h>
+#include <linux/types.h>
#endif
/*
diff --git a/arch/sparc/include/asm/openprom.h b/arch/sparc/include/asm/openprom.h
index aaeae905ed3..963e1a45c35 100644
--- a/arch/sparc/include/asm/openprom.h
+++ b/arch/sparc/include/asm/openprom.h
@@ -1,8 +1,277 @@
-#ifndef ___ASM_SPARC_OPENPROM_H
-#define ___ASM_SPARC_OPENPROM_H
+#ifndef __SPARC_OPENPROM_H
+#define __SPARC_OPENPROM_H
+
+/* openprom.h: Prom structures and defines for access to the OPENBOOT
+ * prom routines and data areas.
+ *
+ * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+/* Empirical constants... */
+#define LINUX_OPPROM_MAGIC 0x10010407
+
+#ifndef __ASSEMBLY__
+/* V0 prom device operations. */
+struct linux_dev_v0_funcs {
+ int (*v0_devopen)(char *device_str);
+ int (*v0_devclose)(int dev_desc);
+ int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
+ int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
+ int (*v0_wrnetdev)(int dev_desc, int num_bytes, char *buf);
+ int (*v0_rdnetdev)(int dev_desc, int num_bytes, char *buf);
+ int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
+ int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
+ int (*v0_seekdev)(int dev_desc, long logical_offst, int from);
+};
+
+/* V2 and later prom device operations. */
+struct linux_dev_v2_funcs {
+ int (*v2_inst2pkg)(int d); /* Convert ihandle to phandle */
+ char * (*v2_dumb_mem_alloc)(char *va, unsigned sz);
+ void (*v2_dumb_mem_free)(char *va, unsigned sz);
+
+ /* To map devices into virtual I/O space. */
+ char * (*v2_dumb_mmap)(char *virta, int which_io, unsigned paddr, unsigned sz);
+ void (*v2_dumb_munmap)(char *virta, unsigned size);
+
+ int (*v2_dev_open)(char *devpath);
+ void (*v2_dev_close)(int d);
+ int (*v2_dev_read)(int d, char *buf, int nbytes);
+ int (*v2_dev_write)(int d, char *buf, int nbytes);
+ int (*v2_dev_seek)(int d, int hi, int lo);
+
+ /* Never issued (multistage load support) */
+ void (*v2_wheee2)(void);
+ void (*v2_wheee3)(void);
+};
+
+struct linux_mlist_v0 {
+ struct linux_mlist_v0 *theres_more;
+ unsigned int start_adr;
+ unsigned num_bytes;
+};
+
+struct linux_mem_v0 {
+ struct linux_mlist_v0 **v0_totphys;
+ struct linux_mlist_v0 **v0_prommap;
+ struct linux_mlist_v0 **v0_available; /* What we can use */
+};
+
+/* Arguments sent to the kernel from the boot prompt. */
+struct linux_arguments_v0 {
+ char *argv[8];
+ char args[100];
+ char boot_dev[2];
+ int boot_dev_ctrl;
+ int boot_dev_unit;
+ int dev_partition;
+ char *kernel_file_name;
+ void *aieee1; /* XXX */
+};
+
+/* V2 and up boot things. */
+struct linux_bootargs_v2 {
+ char **bootpath;
+ char **bootargs;
+ int *fd_stdin;
+ int *fd_stdout;
+};
+
+/* The top level PROM vector. */
+struct linux_romvec {
+ /* Version numbers. */
+ unsigned int pv_magic_cookie;
+ unsigned int pv_romvers;
+ unsigned int pv_plugin_revision;
+ unsigned int pv_printrev;
+
+ /* Version 0 memory descriptors. */
+ struct linux_mem_v0 pv_v0mem;
+
+ /* Node operations. */
+ struct linux_nodeops *pv_nodeops;
+
+ char **pv_bootstr;
+ struct linux_dev_v0_funcs pv_v0devops;
+
+ char *pv_stdin;
+ char *pv_stdout;
+#define PROMDEV_KBD 0 /* input from keyboard */
+#define PROMDEV_SCREEN 0 /* output to screen */
+#define PROMDEV_TTYA 1 /* in/out to ttya */
+#define PROMDEV_TTYB 2 /* in/out to ttyb */
+
+ /* Blocking getchar/putchar. NOT REENTRANT! (grr) */
+ int (*pv_getchar)(void);
+ void (*pv_putchar)(int ch);
+
+ /* Non-blocking variants. */
+ int (*pv_nbgetchar)(void);
+ int (*pv_nbputchar)(int ch);
+
+ void (*pv_putstr)(char *str, int len);
+
+ /* Miscellany. */
+ void (*pv_reboot)(char *bootstr);
+ void (*pv_printf)(__const__ char *fmt, ...);
+ void (*pv_abort)(void);
+ __volatile__ int *pv_ticks;
+ void (*pv_halt)(void);
+ void (**pv_synchook)(void);
+
+ /* Evaluate a forth string, not different proto for V0 and V2->up. */
+ union {
+ void (*v0_eval)(int len, char *str);
+ void (*v2_eval)(char *str);
+ } pv_fortheval;
+
+ struct linux_arguments_v0 **pv_v0bootargs;
+
+ /* Get ether address. */
+ unsigned int (*pv_enaddr)(int d, char *enaddr);
+
+ struct linux_bootargs_v2 pv_v2bootargs;
+ struct linux_dev_v2_funcs pv_v2devops;
+
+ int filler[15];
+
+ /* This one is sun4c/sun4 only. */
+ void (*pv_setctxt)(int ctxt, char *va, int pmeg);
+
+ /* Prom version 3 Multiprocessor routines. This stuff is crazy.
+ * No joke. Calling these when there is only one cpu probably
+ * crashes the machine, have to test this. :-)
+ */
+
+ /* v3_cpustart() will start the cpu 'whichcpu' in mmu-context
+ * 'thiscontext' executing at address 'prog_counter'
+ */
+ int (*v3_cpustart)(unsigned int whichcpu, int ctxtbl_ptr,
+ int thiscontext, char *prog_counter);
+
+ /* v3_cpustop() will cause cpu 'whichcpu' to stop executing
+ * until a resume cpu call is made.
+ */
+ int (*v3_cpustop)(unsigned int whichcpu);
+
+ /* v3_cpuidle() will idle cpu 'whichcpu' until a stop or
+ * resume cpu call is made.
+ */
+ int (*v3_cpuidle)(unsigned int whichcpu);
+
+ /* v3_cpuresume() will resume processor 'whichcpu' executing
+ * starting with whatever 'pc' and 'npc' were left at the
+ * last 'idle' or 'stop' call.
+ */
+ int (*v3_cpuresume)(unsigned int whichcpu);
+};
+
+/* Routines for traversing the prom device tree. */
+struct linux_nodeops {
+ int (*no_nextnode)(int node);
+ int (*no_child)(int node);
+ int (*no_proplen)(int node, const char *name);
+ int (*no_getprop)(int node, const char *name, char *val);
+ int (*no_setprop)(int node, const char *name, char *val, int len);
+ char * (*no_nextprop)(int node, char *name);
+};
+
+/* More fun PROM structures for device probing. */
#if defined(__sparc__) && defined(__arch64__)
-#include <asm/openprom_64.h>
+#define PROMREG_MAX 24
+#define PROMVADDR_MAX 16
+#define PROMINTR_MAX 32
#else
-#include <asm/openprom_32.h>
+#define PROMREG_MAX 16
+#define PROMVADDR_MAX 16
+#define PROMINTR_MAX 15
#endif
+
+struct linux_prom_registers {
+ unsigned int which_io; /* hi part of physical address */
+ unsigned int phys_addr; /* The physical address of this register */
+ unsigned int reg_size; /* How many bytes does this register take up? */
+};
+
+struct linux_prom64_registers {
+ unsigned long phys_addr;
+ unsigned long reg_size;
+};
+
+struct linux_prom_irqs {
+ int pri; /* IRQ priority */
+ int vector; /* This is foobar, what does it do? */
+};
+
+/* Element of the "ranges" vector */
+struct linux_prom_ranges {
+ unsigned int ot_child_space;
+ unsigned int ot_child_base; /* Bus feels this */
+ unsigned int ot_parent_space;
+ unsigned int ot_parent_base; /* CPU looks from here */
+ unsigned int or_size;
+};
+
+/*
+ * Ranges and reg properties are a bit different for PCI.
+ */
+#if defined(__sparc__) && defined(__arch64__)
+struct linux_prom_pci_registers {
+ unsigned int phys_hi;
+ unsigned int phys_mid;
+ unsigned int phys_lo;
+
+ unsigned int size_hi;
+ unsigned int size_lo;
+};
+#else
+struct linux_prom_pci_registers {
+ /*
+ * We don't know what information this field contain.
+ * We guess, PCI device function is in bits 15:8
+ * So, ...
+ */
+ unsigned int which_io; /* Let it be which_io */
+
+ unsigned int phys_hi;
+ unsigned int phys_lo;
+
+ unsigned int size_hi;
+ unsigned int size_lo;
+};
+
#endif
+
+struct linux_prom_pci_ranges {
+ unsigned int child_phys_hi; /* Only certain bits are encoded here. */
+ unsigned int child_phys_mid;
+ unsigned int child_phys_lo;
+
+ unsigned int parent_phys_hi;
+ unsigned int parent_phys_lo;
+
+ unsigned int size_hi;
+ unsigned int size_lo;
+};
+
+struct linux_prom_pci_intmap {
+ unsigned int phys_hi;
+ unsigned int phys_mid;
+ unsigned int phys_lo;
+
+ unsigned int interrupt;
+
+ int cnode;
+ unsigned int cinterrupt;
+};
+
+struct linux_prom_pci_intmask {
+ unsigned int phys_hi;
+ unsigned int phys_mid;
+ unsigned int phys_lo;
+ unsigned int interrupt;
+};
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__SPARC_OPENPROM_H) */
diff --git a/arch/sparc/include/asm/openprom_32.h b/arch/sparc/include/asm/openprom_32.h
deleted file mode 100644
index 875da3552d8..00000000000
--- a/arch/sparc/include/asm/openprom_32.h
+++ /dev/null
@@ -1,255 +0,0 @@
-#ifndef __SPARC_OPENPROM_H
-#define __SPARC_OPENPROM_H
-
-/* openprom.h: Prom structures and defines for access to the OPENBOOT
- * prom routines and data areas.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-/* Empirical constants... */
-#define LINUX_OPPROM_MAGIC 0x10010407
-
-#ifndef __ASSEMBLY__
-/* V0 prom device operations. */
-struct linux_dev_v0_funcs {
- int (*v0_devopen)(char *device_str);
- int (*v0_devclose)(int dev_desc);
- int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
- int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
- int (*v0_wrnetdev)(int dev_desc, int num_bytes, char *buf);
- int (*v0_rdnetdev)(int dev_desc, int num_bytes, char *buf);
- int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
- int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
- int (*v0_seekdev)(int dev_desc, long logical_offst, int from);
-};
-
-/* V2 and later prom device operations. */
-struct linux_dev_v2_funcs {
- int (*v2_inst2pkg)(int d); /* Convert ihandle to phandle */
- char * (*v2_dumb_mem_alloc)(char *va, unsigned sz);
- void (*v2_dumb_mem_free)(char *va, unsigned sz);
-
- /* To map devices into virtual I/O space. */
- char * (*v2_dumb_mmap)(char *virta, int which_io, unsigned paddr, unsigned sz);
- void (*v2_dumb_munmap)(char *virta, unsigned size);
-
- int (*v2_dev_open)(char *devpath);
- void (*v2_dev_close)(int d);
- int (*v2_dev_read)(int d, char *buf, int nbytes);
- int (*v2_dev_write)(int d, char *buf, int nbytes);
- int (*v2_dev_seek)(int d, int hi, int lo);
-
- /* Never issued (multistage load support) */
- void (*v2_wheee2)(void);
- void (*v2_wheee3)(void);
-};
-
-struct linux_mlist_v0 {
- struct linux_mlist_v0 *theres_more;
- char *start_adr;
- unsigned num_bytes;
-};
-
-struct linux_mem_v0 {
- struct linux_mlist_v0 **v0_totphys;
- struct linux_mlist_v0 **v0_prommap;
- struct linux_mlist_v0 **v0_available; /* What we can use */
-};
-
-/* Arguments sent to the kernel from the boot prompt. */
-struct linux_arguments_v0 {
- char *argv[8];
- char args[100];
- char boot_dev[2];
- int boot_dev_ctrl;
- int boot_dev_unit;
- int dev_partition;
- char *kernel_file_name;
- void *aieee1; /* XXX */
-};
-
-/* V2 and up boot things. */
-struct linux_bootargs_v2 {
- char **bootpath;
- char **bootargs;
- int *fd_stdin;
- int *fd_stdout;
-};
-
-/* The top level PROM vector. */
-struct linux_romvec {
- /* Version numbers. */
- unsigned int pv_magic_cookie;
- unsigned int pv_romvers;
- unsigned int pv_plugin_revision;
- unsigned int pv_printrev;
-
- /* Version 0 memory descriptors. */
- struct linux_mem_v0 pv_v0mem;
-
- /* Node operations. */
- struct linux_nodeops *pv_nodeops;
-
- char **pv_bootstr;
- struct linux_dev_v0_funcs pv_v0devops;
-
- char *pv_stdin;
- char *pv_stdout;
-#define PROMDEV_KBD 0 /* input from keyboard */
-#define PROMDEV_SCREEN 0 /* output to screen */
-#define PROMDEV_TTYA 1 /* in/out to ttya */
-#define PROMDEV_TTYB 2 /* in/out to ttyb */
-
- /* Blocking getchar/putchar. NOT REENTRANT! (grr) */
- int (*pv_getchar)(void);
- void (*pv_putchar)(int ch);
-
- /* Non-blocking variants. */
- int (*pv_nbgetchar)(void);
- int (*pv_nbputchar)(int ch);
-
- void (*pv_putstr)(char *str, int len);
-
- /* Miscellany. */
- void (*pv_reboot)(char *bootstr);
- void (*pv_printf)(__const__ char *fmt, ...);
- void (*pv_abort)(void);
- __volatile__ int *pv_ticks;
- void (*pv_halt)(void);
- void (**pv_synchook)(void);
-
- /* Evaluate a forth string, not different proto for V0 and V2->up. */
- union {
- void (*v0_eval)(int len, char *str);
- void (*v2_eval)(char *str);
- } pv_fortheval;
-
- struct linux_arguments_v0 **pv_v0bootargs;
-
- /* Get ether address. */
- unsigned int (*pv_enaddr)(int d, char *enaddr);
-
- struct linux_bootargs_v2 pv_v2bootargs;
- struct linux_dev_v2_funcs pv_v2devops;
-
- int filler[15];
-
- /* This one is sun4c/sun4 only. */
- void (*pv_setctxt)(int ctxt, char *va, int pmeg);
-
- /* Prom version 3 Multiprocessor routines. This stuff is crazy.
- * No joke. Calling these when there is only one cpu probably
- * crashes the machine, have to test this. :-)
- */
-
- /* v3_cpustart() will start the cpu 'whichcpu' in mmu-context
- * 'thiscontext' executing at address 'prog_counter'
- */
- int (*v3_cpustart)(unsigned int whichcpu, int ctxtbl_ptr,
- int thiscontext, char *prog_counter);
-
- /* v3_cpustop() will cause cpu 'whichcpu' to stop executing
- * until a resume cpu call is made.
- */
- int (*v3_cpustop)(unsigned int whichcpu);
-
- /* v3_cpuidle() will idle cpu 'whichcpu' until a stop or
- * resume cpu call is made.
- */
- int (*v3_cpuidle)(unsigned int whichcpu);
-
- /* v3_cpuresume() will resume processor 'whichcpu' executing
- * starting with whatever 'pc' and 'npc' were left at the
- * last 'idle' or 'stop' call.
- */
- int (*v3_cpuresume)(unsigned int whichcpu);
-};
-
-/* Routines for traversing the prom device tree. */
-struct linux_nodeops {
- int (*no_nextnode)(int node);
- int (*no_child)(int node);
- int (*no_proplen)(int node, const char *name);
- int (*no_getprop)(int node, const char *name, char *val);
- int (*no_setprop)(int node, const char *name, char *val, int len);
- char * (*no_nextprop)(int node, char *name);
-};
-
-/* More fun PROM structures for device probing. */
-#define PROMREG_MAX 16
-#define PROMVADDR_MAX 16
-#define PROMINTR_MAX 15
-
-struct linux_prom_registers {
- unsigned int which_io; /* is this in OBIO space? */
- unsigned int phys_addr; /* The physical address of this register */
- unsigned int reg_size; /* How many bytes does this register take up? */
-};
-
-struct linux_prom_irqs {
- int pri; /* IRQ priority */
- int vector; /* This is foobar, what does it do? */
-};
-
-/* Element of the "ranges" vector */
-struct linux_prom_ranges {
- unsigned int ot_child_space;
- unsigned int ot_child_base; /* Bus feels this */
- unsigned int ot_parent_space;
- unsigned int ot_parent_base; /* CPU looks from here */
- unsigned int or_size;
-};
-
-/* Ranges and reg properties are a bit different for PCI. */
-struct linux_prom_pci_registers {
- /*
- * We don't know what information this field contain.
- * We guess, PCI device function is in bits 15:8
- * So, ...
- */
- unsigned int which_io; /* Let it be which_io */
-
- unsigned int phys_hi;
- unsigned int phys_lo;
-
- unsigned int size_hi;
- unsigned int size_lo;
-};
-
-struct linux_prom_pci_ranges {
- unsigned int child_phys_hi; /* Only certain bits are encoded here. */
- unsigned int child_phys_mid;
- unsigned int child_phys_lo;
-
- unsigned int parent_phys_hi;
- unsigned int parent_phys_lo;
-
- unsigned int size_hi;
- unsigned int size_lo;
-};
-
-struct linux_prom_pci_assigned_addresses {
- unsigned int which_io;
-
- unsigned int phys_hi;
- unsigned int phys_lo;
-
- unsigned int size_hi;
- unsigned int size_lo;
-};
-
-struct linux_prom_ebus_ranges {
- unsigned int child_phys_hi;
- unsigned int child_phys_lo;
-
- unsigned int parent_phys_hi;
- unsigned int parent_phys_mid;
- unsigned int parent_phys_lo;
-
- unsigned int size;
-};
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(__SPARC_OPENPROM_H) */
diff --git a/arch/sparc/include/asm/openprom_64.h b/arch/sparc/include/asm/openprom_64.h
deleted file mode 100644
index b69e4a8c917..00000000000
--- a/arch/sparc/include/asm/openprom_64.h
+++ /dev/null
@@ -1,280 +0,0 @@
-#ifndef __SPARC64_OPENPROM_H
-#define __SPARC64_OPENPROM_H
-
-/* openprom.h: Prom structures and defines for access to the OPENBOOT
- * prom routines and data areas.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef __ASSEMBLY__
-/* V0 prom device operations. */
-struct linux_dev_v0_funcs {
- int (*v0_devopen)(char *device_str);
- int (*v0_devclose)(int dev_desc);
- int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
- int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
- int (*v0_wrnetdev)(int dev_desc, int num_bytes, char *buf);
- int (*v0_rdnetdev)(int dev_desc, int num_bytes, char *buf);
- int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
- int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
- int (*v0_seekdev)(int dev_desc, long logical_offst, int from);
-};
-
-/* V2 and later prom device operations. */
-struct linux_dev_v2_funcs {
- int (*v2_inst2pkg)(int d); /* Convert ihandle to phandle */
- char * (*v2_dumb_mem_alloc)(char *va, unsigned sz);
- void (*v2_dumb_mem_free)(char *va, unsigned sz);
-
- /* To map devices into virtual I/O space. */
- char * (*v2_dumb_mmap)(char *virta, int which_io, unsigned paddr, unsigned sz);
- void (*v2_dumb_munmap)(char *virta, unsigned size);
-
- int (*v2_dev_open)(char *devpath);
- void (*v2_dev_close)(int d);
- int (*v2_dev_read)(int d, char *buf, int nbytes);
- int (*v2_dev_write)(int d, char *buf, int nbytes);
- int (*v2_dev_seek)(int d, int hi, int lo);
-
- /* Never issued (multistage load support) */
- void (*v2_wheee2)(void);
- void (*v2_wheee3)(void);
-};
-
-struct linux_mlist_v0 {
- struct linux_mlist_v0 *theres_more;
- unsigned start_adr;
- unsigned num_bytes;
-};
-
-struct linux_mem_v0 {
- struct linux_mlist_v0 **v0_totphys;
- struct linux_mlist_v0 **v0_prommap;
- struct linux_mlist_v0 **v0_available; /* What we can use */
-};
-
-/* Arguments sent to the kernel from the boot prompt. */
-struct linux_arguments_v0 {
- char *argv[8];
- char args[100];
- char boot_dev[2];
- int boot_dev_ctrl;
- int boot_dev_unit;
- int dev_partition;
- char *kernel_file_name;
- void *aieee1; /* XXX */
-};
-
-/* V2 and up boot things. */
-struct linux_bootargs_v2 {
- char **bootpath;
- char **bootargs;
- int *fd_stdin;
- int *fd_stdout;
-};
-
-/* The top level PROM vector. */
-struct linux_romvec {
- /* Version numbers. */
- unsigned int pv_magic_cookie;
- unsigned int pv_romvers;
- unsigned int pv_plugin_revision;
- unsigned int pv_printrev;
-
- /* Version 0 memory descriptors. */
- struct linux_mem_v0 pv_v0mem;
-
- /* Node operations. */
- struct linux_nodeops *pv_nodeops;
-
- char **pv_bootstr;
- struct linux_dev_v0_funcs pv_v0devops;
-
- char *pv_stdin;
- char *pv_stdout;
-#define PROMDEV_KBD 0 /* input from keyboard */
-#define PROMDEV_SCREEN 0 /* output to screen */
-#define PROMDEV_TTYA 1 /* in/out to ttya */
-#define PROMDEV_TTYB 2 /* in/out to ttyb */
-
- /* Blocking getchar/putchar. NOT REENTRANT! (grr) */
- int (*pv_getchar)(void);
- void (*pv_putchar)(int ch);
-
- /* Non-blocking variants. */
- int (*pv_nbgetchar)(void);
- int (*pv_nbputchar)(int ch);
-
- void (*pv_putstr)(char *str, int len);
-
- /* Miscellany. */
- void (*pv_reboot)(char *bootstr);
- void (*pv_printf)(__const__ char *fmt, ...);
- void (*pv_abort)(void);
- __volatile__ int *pv_ticks;
- void (*pv_halt)(void);
- void (**pv_synchook)(void);
-
- /* Evaluate a forth string, not different proto for V0 and V2->up. */
- union {
- void (*v0_eval)(int len, char *str);
- void (*v2_eval)(char *str);
- } pv_fortheval;
-
- struct linux_arguments_v0 **pv_v0bootargs;
-
- /* Get ether address. */
- unsigned int (*pv_enaddr)(int d, char *enaddr);
-
- struct linux_bootargs_v2 pv_v2bootargs;
- struct linux_dev_v2_funcs pv_v2devops;
-
- int filler[15];
-
- /* This one is sun4c/sun4 only. */
- void (*pv_setctxt)(int ctxt, char *va, int pmeg);
-
- /* Prom version 3 Multiprocessor routines. This stuff is crazy.
- * No joke. Calling these when there is only one cpu probably
- * crashes the machine, have to test this. :-)
- */
-
- /* v3_cpustart() will start the cpu 'whichcpu' in mmu-context
- * 'thiscontext' executing at address 'prog_counter'
- */
- int (*v3_cpustart)(unsigned int whichcpu, int ctxtbl_ptr,
- int thiscontext, char *prog_counter);
-
- /* v3_cpustop() will cause cpu 'whichcpu' to stop executing
- * until a resume cpu call is made.
- */
- int (*v3_cpustop)(unsigned int whichcpu);
-
- /* v3_cpuidle() will idle cpu 'whichcpu' until a stop or
- * resume cpu call is made.
- */
- int (*v3_cpuidle)(unsigned int whichcpu);
-
- /* v3_cpuresume() will resume processor 'whichcpu' executing
- * starting with whatever 'pc' and 'npc' were left at the
- * last 'idle' or 'stop' call.
- */
- int (*v3_cpuresume)(unsigned int whichcpu);
-};
-
-/* Routines for traversing the prom device tree. */
-struct linux_nodeops {
- int (*no_nextnode)(int node);
- int (*no_child)(int node);
- int (*no_proplen)(int node, char *name);
- int (*no_getprop)(int node, char *name, char *val);
- int (*no_setprop)(int node, char *name, char *val, int len);
- char * (*no_nextprop)(int node, char *name);
-};
-
-/* More fun PROM structures for device probing. */
-#define PROMREG_MAX 24
-#define PROMVADDR_MAX 16
-#define PROMINTR_MAX 32
-
-struct linux_prom_registers {
- unsigned which_io; /* hi part of physical address */
- unsigned phys_addr; /* The physical address of this register */
- int reg_size; /* How many bytes does this register take up? */
-};
-
-struct linux_prom64_registers {
- unsigned long phys_addr;
- unsigned long reg_size;
-};
-
-struct linux_prom_irqs {
- int pri; /* IRQ priority */
- int vector; /* This is foobar, what does it do? */
-};
-
-/* Element of the "ranges" vector */
-struct linux_prom_ranges {
- unsigned int ot_child_space;
- unsigned int ot_child_base; /* Bus feels this */
- unsigned int ot_parent_space;
- unsigned int ot_parent_base; /* CPU looks from here */
- unsigned int or_size;
-};
-
-struct linux_prom64_ranges {
- unsigned long ot_child_base; /* Bus feels this */
- unsigned long ot_parent_base; /* CPU looks from here */
- unsigned long or_size;
-};
-
-/* Ranges and reg properties are a bit different for PCI. */
-struct linux_prom_pci_registers {
- unsigned int phys_hi;
- unsigned int phys_mid;
- unsigned int phys_lo;
-
- unsigned int size_hi;
- unsigned int size_lo;
-};
-
-struct linux_prom_pci_ranges {
- unsigned int child_phys_hi; /* Only certain bits are encoded here. */
- unsigned int child_phys_mid;
- unsigned int child_phys_lo;
-
- unsigned int parent_phys_hi;
- unsigned int parent_phys_lo;
-
- unsigned int size_hi;
- unsigned int size_lo;
-};
-
-struct linux_prom_pci_intmap {
- unsigned int phys_hi;
- unsigned int phys_mid;
- unsigned int phys_lo;
-
- unsigned int interrupt;
-
- int cnode;
- unsigned int cinterrupt;
-};
-
-struct linux_prom_pci_intmask {
- unsigned int phys_hi;
- unsigned int phys_mid;
- unsigned int phys_lo;
- unsigned int interrupt;
-};
-
-struct linux_prom_ebus_ranges {
- unsigned int child_phys_hi;
- unsigned int child_phys_lo;
-
- unsigned int parent_phys_hi;
- unsigned int parent_phys_mid;
- unsigned int parent_phys_lo;
-
- unsigned int size;
-};
-
-struct linux_prom_ebus_intmap {
- unsigned int phys_hi;
- unsigned int phys_lo;
-
- unsigned int interrupt;
-
- int cnode;
- unsigned int cinterrupt;
-};
-
-struct linux_prom_ebus_intmask {
- unsigned int phys_hi;
- unsigned int phys_lo;
- unsigned int interrupt;
-};
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(__SPARC64_OPENPROM_H) */
diff --git a/arch/sparc/include/asm/posix_types.h b/arch/sparc/include/asm/posix_types.h
index 03a0e091a88..98d6ebb922f 100644
--- a/arch/sparc/include/asm/posix_types.h
+++ b/arch/sparc/include/asm/posix_types.h
@@ -1,8 +1,155 @@
-#ifndef ___ASM_SPARC_POSIX_TYPES_H
-#define ___ASM_SPARC_POSIX_TYPES_H
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc. Also, we cannot
+ * assume GCC is being used.
+ */
+
+#ifndef __SPARC_POSIX_TYPES_H
+#define __SPARC_POSIX_TYPES_H
+
#if defined(__sparc__) && defined(__arch64__)
-#include <asm/posix_types_64.h>
+/* sparc 64 bit */
+typedef unsigned long __kernel_size_t;
+typedef long __kernel_ssize_t;
+typedef long __kernel_ptrdiff_t;
+typedef long __kernel_time_t;
+typedef long __kernel_clock_t;
+typedef int __kernel_pid_t;
+typedef int __kernel_ipc_pid_t;
+typedef unsigned int __kernel_uid_t;
+typedef unsigned int __kernel_gid_t;
+typedef unsigned long __kernel_ino_t;
+typedef unsigned int __kernel_mode_t;
+typedef unsigned short __kernel_umode_t;
+typedef unsigned int __kernel_nlink_t;
+typedef int __kernel_daddr_t;
+typedef long __kernel_off_t;
+typedef char * __kernel_caddr_t;
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+typedef int __kernel_clockid_t;
+typedef int __kernel_timer_t;
+
+typedef unsigned short __kernel_old_uid_t;
+typedef unsigned short __kernel_old_gid_t;
+typedef __kernel_uid_t __kernel_uid32_t;
+typedef __kernel_gid_t __kernel_gid32_t;
+
+typedef unsigned int __kernel_old_dev_t;
+
+/* Note this piece of asymmetry from the v9 ABI. */
+typedef int __kernel_suseconds_t;
+
#else
-#include <asm/posix_types_32.h>
-#endif
+/* sparc 32 bit */
+
+typedef unsigned int __kernel_size_t;
+typedef int __kernel_ssize_t;
+typedef long int __kernel_ptrdiff_t;
+typedef long __kernel_time_t;
+typedef long __kernel_suseconds_t;
+typedef long __kernel_clock_t;
+typedef int __kernel_pid_t;
+typedef unsigned short __kernel_ipc_pid_t;
+typedef unsigned short __kernel_uid_t;
+typedef unsigned short __kernel_gid_t;
+typedef unsigned long __kernel_ino_t;
+typedef unsigned short __kernel_mode_t;
+typedef unsigned short __kernel_umode_t;
+typedef short __kernel_nlink_t;
+typedef long __kernel_daddr_t;
+typedef long __kernel_off_t;
+typedef char * __kernel_caddr_t;
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+typedef unsigned int __kernel_uid32_t;
+typedef unsigned int __kernel_gid32_t;
+typedef unsigned short __kernel_old_uid_t;
+typedef unsigned short __kernel_old_gid_t;
+typedef unsigned short __kernel_old_dev_t;
+typedef int __kernel_clockid_t;
+typedef int __kernel_timer_t;
+
+#endif /* defined(__sparc__) && defined(__arch64__) */
+
+#ifdef __GNUC__
+typedef long long __kernel_loff_t;
#endif
+
+typedef struct {
+ int val[2];
+} __kernel_fsid_t;
+
+#ifdef __KERNEL__
+
+#undef __FD_SET
+static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
+{
+ unsigned long _tmp = fd / __NFDBITS;
+ unsigned long _rem = fd % __NFDBITS;
+ fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
+}
+
+#undef __FD_CLR
+static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
+{
+ unsigned long _tmp = fd / __NFDBITS;
+ unsigned long _rem = fd % __NFDBITS;
+ fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
+}
+
+#undef __FD_ISSET
+static inline int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
+{
+ unsigned long _tmp = fd / __NFDBITS;
+ unsigned long _rem = fd % __NFDBITS;
+ return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
+}
+
+/*
+ * This will unroll the loop for the normal constant cases (8 or 32 longs,
+ * for 256 and 1024-bit fd_sets respectively)
+ */
+#undef __FD_ZERO
+static inline void __FD_ZERO(__kernel_fd_set *p)
+{
+ unsigned long *tmp = p->fds_bits;
+ int i;
+
+ if (__builtin_constant_p(__FDSET_LONGS)) {
+ switch (__FDSET_LONGS) {
+ case 32:
+ tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+ tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
+ tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
+ tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
+ tmp[16] = 0; tmp[17] = 0; tmp[18] = 0; tmp[19] = 0;
+ tmp[20] = 0; tmp[21] = 0; tmp[22] = 0; tmp[23] = 0;
+ tmp[24] = 0; tmp[25] = 0; tmp[26] = 0; tmp[27] = 0;
+ tmp[28] = 0; tmp[29] = 0; tmp[30] = 0; tmp[31] = 0;
+ return;
+ case 16:
+ tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+ tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
+ tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
+ tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
+ return;
+ case 8:
+ tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+ tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
+ return;
+ case 4:
+ tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+ return;
+ }
+ }
+ i = __FDSET_LONGS;
+ while (i) {
+ i--;
+ *tmp = 0;
+ tmp++;
+ }
+}
+
+#endif /* __KERNEL__ */
+#endif /* __SPARC_POSIX_TYPES_H */
diff --git a/arch/sparc/include/asm/posix_types_32.h b/arch/sparc/include/asm/posix_types_32.h
deleted file mode 100644
index 6bb6eb1ca0f..00000000000
--- a/arch/sparc/include/asm/posix_types_32.h
+++ /dev/null
@@ -1,118 +0,0 @@
-#ifndef __ARCH_SPARC_POSIX_TYPES_H
-#define __ARCH_SPARC_POSIX_TYPES_H
-
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc. Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned int __kernel_size_t;
-typedef int __kernel_ssize_t;
-typedef long int __kernel_ptrdiff_t;
-typedef long __kernel_time_t;
-typedef long __kernel_suseconds_t;
-typedef long __kernel_clock_t;
-typedef int __kernel_pid_t;
-typedef unsigned short __kernel_ipc_pid_t;
-typedef unsigned short __kernel_uid_t;
-typedef unsigned short __kernel_gid_t;
-typedef unsigned long __kernel_ino_t;
-typedef unsigned short __kernel_mode_t;
-typedef unsigned short __kernel_umode_t;
-typedef short __kernel_nlink_t;
-typedef long __kernel_daddr_t;
-typedef long __kernel_off_t;
-typedef char * __kernel_caddr_t;
-typedef unsigned short __kernel_uid16_t;
-typedef unsigned short __kernel_gid16_t;
-typedef unsigned int __kernel_uid32_t;
-typedef unsigned int __kernel_gid32_t;
-typedef unsigned short __kernel_old_uid_t;
-typedef unsigned short __kernel_old_gid_t;
-typedef unsigned short __kernel_old_dev_t;
-typedef int __kernel_clockid_t;
-typedef int __kernel_timer_t;
-
-#ifdef __GNUC__
-typedef long long __kernel_loff_t;
-#endif
-
-typedef struct {
- int val[2];
-} __kernel_fsid_t;
-
-#if defined(__KERNEL__)
-
-#undef __FD_SET
-static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
-{
- unsigned long _tmp = fd / __NFDBITS;
- unsigned long _rem = fd % __NFDBITS;
- fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
-}
-
-#undef __FD_CLR
-static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
-{
- unsigned long _tmp = fd / __NFDBITS;
- unsigned long _rem = fd % __NFDBITS;
- fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
-}
-
-#undef __FD_ISSET
-static inline int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
-{
- unsigned long _tmp = fd / __NFDBITS;
- unsigned long _rem = fd % __NFDBITS;
- return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant cases (8 or 32 longs,
- * for 256 and 1024-bit fd_sets respectively)
- */
-#undef __FD_ZERO
-static inline void __FD_ZERO(__kernel_fd_set *p)
-{
- unsigned long *tmp = p->fds_bits;
- int i;
-
- if (__builtin_constant_p(__FDSET_LONGS)) {
- switch (__FDSET_LONGS) {
- case 32:
- tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
- tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
- tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
- tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
- tmp[16] = 0; tmp[17] = 0; tmp[18] = 0; tmp[19] = 0;
- tmp[20] = 0; tmp[21] = 0; tmp[22] = 0; tmp[23] = 0;
- tmp[24] = 0; tmp[25] = 0; tmp[26] = 0; tmp[27] = 0;
- tmp[28] = 0; tmp[29] = 0; tmp[30] = 0; tmp[31] = 0;
- return;
- case 16:
- tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
- tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
- tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
- tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
- return;
- case 8:
- tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
- tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
- return;
- case 4:
- tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
- return;
- }
- }
- i = __FDSET_LONGS;
- while (i) {
- i--;
- *tmp = 0;
- tmp++;
- }
-}
-
-#endif /* defined(__KERNEL__) */
-
-#endif /* !(__ARCH_SPARC_POSIX_TYPES_H) */
diff --git a/arch/sparc/include/asm/posix_types_64.h b/arch/sparc/include/asm/posix_types_64.h
deleted file mode 100644
index ba8f9329576..00000000000
--- a/arch/sparc/include/asm/posix_types_64.h
+++ /dev/null
@@ -1,122 +0,0 @@
-#ifndef __ARCH_SPARC64_POSIX_TYPES_H
-#define __ARCH_SPARC64_POSIX_TYPES_H
-
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc. Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned long __kernel_size_t;
-typedef long __kernel_ssize_t;
-typedef long __kernel_ptrdiff_t;
-typedef long __kernel_time_t;
-typedef long __kernel_clock_t;
-typedef int __kernel_pid_t;
-typedef int __kernel_ipc_pid_t;
-typedef unsigned int __kernel_uid_t;
-typedef unsigned int __kernel_gid_t;
-typedef unsigned long __kernel_ino_t;
-typedef unsigned int __kernel_mode_t;
-typedef unsigned short __kernel_umode_t;
-typedef unsigned int __kernel_nlink_t;
-typedef int __kernel_daddr_t;
-typedef long __kernel_off_t;
-typedef char * __kernel_caddr_t;
-typedef unsigned short __kernel_uid16_t;
-typedef unsigned short __kernel_gid16_t;
-typedef int __kernel_clockid_t;
-typedef int __kernel_timer_t;
-
-typedef unsigned short __kernel_old_uid_t;
-typedef unsigned short __kernel_old_gid_t;
-typedef __kernel_uid_t __kernel_uid32_t;
-typedef __kernel_gid_t __kernel_gid32_t;
-
-typedef unsigned int __kernel_old_dev_t;
-
-/* Note this piece of asymmetry from the v9 ABI. */
-typedef int __kernel_suseconds_t;
-
-#ifdef __GNUC__
-typedef long long __kernel_loff_t;
-#endif
-
-typedef struct {
- int val[2];
-} __kernel_fsid_t;
-
-#if defined(__KERNEL__)
-
-#undef __FD_SET
-static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
-{
- unsigned long _tmp = fd / __NFDBITS;
- unsigned long _rem = fd % __NFDBITS;
- fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
-}
-
-#undef __FD_CLR
-static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
-{
- unsigned long _tmp = fd / __NFDBITS;
- unsigned long _rem = fd % __NFDBITS;
- fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
-}
-
-#undef __FD_ISSET
-static inline int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
-{
- unsigned long _tmp = fd / __NFDBITS;
- unsigned long _rem = fd % __NFDBITS;
- return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant cases (8 or 32 longs,
- * for 256 and 1024-bit fd_sets respectively)
- */
-#undef __FD_ZERO
-static inline void __FD_ZERO(__kernel_fd_set *p)
-{
- unsigned long *tmp = p->fds_bits;
- int i;
-
- if (__builtin_constant_p(__FDSET_LONGS)) {
- switch (__FDSET_LONGS) {
- case 32:
- tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
- tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
- tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
- tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
- tmp[16] = 0; tmp[17] = 0; tmp[18] = 0; tmp[19] = 0;
- tmp[20] = 0; tmp[21] = 0; tmp[22] = 0; tmp[23] = 0;
- tmp[24] = 0; tmp[25] = 0; tmp[26] = 0; tmp[27] = 0;
- tmp[28] = 0; tmp[29] = 0; tmp[30] = 0; tmp[31] = 0;
- return;
- case 16:
- tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
- tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
- tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
- tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
- return;
- case 8:
- tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
- tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
- return;
- case 4:
- tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
- return;
- }
- }
- i = __FDSET_LONGS;
- while (i) {
- i--;
- *tmp = 0;
- tmp++;
- }
-}
-
-#endif /* defined(__KERNEL__) */
-
-#endif /* !(__ARCH_SPARC64_POSIX_TYPES_H) */
diff --git a/arch/sparc/include/asm/processor_32.h b/arch/sparc/include/asm/processor_32.h
index 2ae67a2e7f3..09521c6a5ed 100644
--- a/arch/sparc/include/asm/processor_32.h
+++ b/arch/sparc/include/asm/processor_32.h
@@ -99,7 +99,7 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc,
"st\t%%g0, [%0 + %3 + 0x3c]"
: /* no outputs */
: "r" (regs),
- "r" (sp - sizeof(struct reg_window)),
+ "r" (sp - sizeof(struct reg_window32)),
"r" (zero),
"i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))
: "memory");
diff --git a/arch/sparc/include/asm/ptrace.h b/arch/sparc/include/asm/ptrace.h
index 6dcbe2eed2e..30b0b797dc0 100644
--- a/arch/sparc/include/asm/ptrace.h
+++ b/arch/sparc/include/asm/ptrace.h
@@ -1,8 +1,448 @@
-#ifndef ___ASM_SPARC_PTRACE_H
-#define ___ASM_SPARC_PTRACE_H
+#ifndef __SPARC_PTRACE_H
+#define __SPARC_PTRACE_H
+
#if defined(__sparc__) && defined(__arch64__)
-#include <asm/ptrace_64.h>
+/* 64 bit sparc */
+#include <asm/pstate.h>
+
+/* This struct defines the way the registers are stored on the
+ * stack during a system call and basically all traps.
+ */
+
+/* This magic value must have the low 9 bits clear,
+ * as that is where we encode the %tt value, see below.
+ */
+#define PT_REGS_MAGIC 0x57ac6c00
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+struct pt_regs {
+ unsigned long u_regs[16]; /* globals and ins */
+ unsigned long tstate;
+ unsigned long tpc;
+ unsigned long tnpc;
+ unsigned int y;
+
+ /* We encode a magic number, PT_REGS_MAGIC, along
+ * with the %tt (trap type) register value at trap
+ * entry time. The magic number allows us to identify
+ * accurately a trap stack frame in the stack
+ * unwinder, and the %tt value allows us to test
+ * things like "in a system call" etc. for an arbitray
+ * process.
+ *
+ * The PT_REGS_MAGIC is choosen such that it can be
+ * loaded completely using just a sethi instruction.
+ */
+ unsigned int magic;
+};
+
+struct pt_regs32 {
+ unsigned int psr;
+ unsigned int pc;
+ unsigned int npc;
+ unsigned int y;
+ unsigned int u_regs[16]; /* globals and ins */
+};
+
+/* A V9 register window */
+struct reg_window {
+ unsigned long locals[8];
+ unsigned long ins[8];
+};
+
+/* A 32-bit register window. */
+struct reg_window32 {
+ unsigned int locals[8];
+ unsigned int ins[8];
+};
+
+/* A V9 Sparc stack frame */
+struct sparc_stackf {
+ unsigned long locals[8];
+ unsigned long ins[6];
+ struct sparc_stackf *fp;
+ unsigned long callers_pc;
+ char *structptr;
+ unsigned long xargs[6];
+ unsigned long xxargs[1];
+};
+
+/* A 32-bit Sparc stack frame */
+struct sparc_stackf32 {
+ unsigned int locals[8];
+ unsigned int ins[6];
+ unsigned int fp;
+ unsigned int callers_pc;
+ unsigned int structptr;
+ unsigned int xargs[6];
+ unsigned int xxargs[1];
+};
+
+struct sparc_trapf {
+ unsigned long locals[8];
+ unsigned long ins[8];
+ unsigned long _unused;
+ struct pt_regs *regs;
+};
+#endif /* (!__ASSEMBLY__) */
#else
-#include <asm/ptrace_32.h>
+/* 32 bit sparc */
+
+#include <asm/psr.h>
+
+/* This struct defines the way the registers are stored on the
+ * stack during a system call and basically all traps.
+ */
+#ifndef __ASSEMBLY__
+
+struct pt_regs {
+ unsigned long psr;
+ unsigned long pc;
+ unsigned long npc;
+ unsigned long y;
+ unsigned long u_regs[16]; /* globals and ins */
+};
+
+/* A 32-bit register window. */
+struct reg_window32 {
+ unsigned long locals[8];
+ unsigned long ins[8];
+};
+
+/* A Sparc stack frame */
+struct sparc_stackf {
+ unsigned long locals[8];
+ unsigned long ins[6];
+ struct sparc_stackf *fp;
+ unsigned long callers_pc;
+ char *structptr;
+ unsigned long xargs[6];
+ unsigned long xxargs[1];
+};
+#endif /* (!__ASSEMBLY__) */
+
+#endif /* (defined(__sparc__) && defined(__arch64__))*/
+
+#ifndef __ASSEMBLY__
+
+#define TRACEREG_SZ sizeof(struct pt_regs)
+#define STACKFRAME_SZ sizeof(struct sparc_stackf)
+
+#define TRACEREG32_SZ sizeof(struct pt_regs32)
+#define STACKFRAME32_SZ sizeof(struct sparc_stackf32)
+
+#endif /* (!__ASSEMBLY__) */
+
+#define UREG_G0 0
+#define UREG_G1 1
+#define UREG_G2 2
+#define UREG_G3 3
+#define UREG_G4 4
+#define UREG_G5 5
+#define UREG_G6 6
+#define UREG_G7 7
+#define UREG_I0 8
+#define UREG_I1 9
+#define UREG_I2 10
+#define UREG_I3 11
+#define UREG_I4 12
+#define UREG_I5 13
+#define UREG_I6 14
+#define UREG_I7 15
+#define UREG_FP UREG_I6
+#define UREG_RETPC UREG_I7
+
+#if defined(__sparc__) && defined(__arch64__)
+/* 64 bit sparc */
+
+#ifndef __ASSEMBLY__
+
+#ifdef __KERNEL__
+
+#include <linux/threads.h>
+#include <asm/system.h>
+
+static inline int pt_regs_trap_type(struct pt_regs *regs)
+{
+ return regs->magic & 0x1ff;
+}
+
+static inline bool pt_regs_is_syscall(struct pt_regs *regs)
+{
+ return (regs->tstate & TSTATE_SYSCALL);
+}
+
+static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
+{
+ return (regs->tstate &= ~TSTATE_SYSCALL);
+}
+
+#define arch_ptrace_stop_needed(exit_code, info) \
+({ flush_user_windows(); \
+ get_thread_wsaved() != 0; \
+})
+
+#define arch_ptrace_stop(exit_code, info) \
+ synchronize_user_stack()
+
+struct global_reg_snapshot {
+ unsigned long tstate;
+ unsigned long tpc;
+ unsigned long tnpc;
+ unsigned long o7;
+ unsigned long i7;
+ unsigned long rpc;
+ struct thread_info *thread;
+ unsigned long pad1;
+};
+extern struct global_reg_snapshot global_reg_snapshot[NR_CPUS];
+
+#define force_successful_syscall_return() \
+do { current_thread_info()->syscall_noerror = 1; \
+} while (0)
+#define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
+#define instruction_pointer(regs) ((regs)->tpc)
+#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
+#define regs_return_value(regs) ((regs)->u_regs[UREG_I0])
+#ifdef CONFIG_SMP
+extern unsigned long profile_pc(struct pt_regs *);
+#else
+#define profile_pc(regs) instruction_pointer(regs)
#endif
+extern void show_regs(struct pt_regs *);
+#endif /* (__KERNEL__) */
+
+#else /* __ASSEMBLY__ */
+/* For assembly code. */
+#define TRACEREG_SZ 0xa0
+#define STACKFRAME_SZ 0xc0
+
+#define TRACEREG32_SZ 0x50
+#define STACKFRAME32_SZ 0x60
+#endif /* __ASSEMBLY__ */
+
+#else /* (defined(__sparc__) && defined(__arch64__)) */
+
+/* 32 bit sparc */
+
+#ifndef __ASSEMBLY__
+
+#ifdef __KERNEL__
+
+#include <asm/system.h>
+
+static inline bool pt_regs_is_syscall(struct pt_regs *regs)
+{
+ return (regs->psr & PSR_SYSCALL);
+}
+
+static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
+{
+ return (regs->psr &= ~PSR_SYSCALL);
+}
+
+#define arch_ptrace_stop_needed(exit_code, info) \
+({ flush_user_windows(); \
+ current_thread_info()->w_saved != 0; \
+})
+
+#define arch_ptrace_stop(exit_code, info) \
+ synchronize_user_stack()
+
+#define user_mode(regs) (!((regs)->psr & PSR_PS))
+#define instruction_pointer(regs) ((regs)->pc)
+#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
+unsigned long profile_pc(struct pt_regs *);
+extern void show_regs(struct pt_regs *);
+#endif /* (__KERNEL__) */
+
+#else /* (!__ASSEMBLY__) */
+/* For assembly code. */
+#define TRACEREG_SZ 0x50
+#define STACKFRAME_SZ 0x60
+#endif /* (!__ASSEMBLY__) */
+
+#endif /* (defined(__sparc__) && defined(__arch64__)) */
+
+#ifdef __KERNEL__
+#define STACK_BIAS 2047
#endif
+
+/* These are for pt_regs. */
+#define PT_V9_G0 0x00
+#define PT_V9_G1 0x08
+#define PT_V9_G2 0x10
+#define PT_V9_G3 0x18
+#define PT_V9_G4 0x20
+#define PT_V9_G5 0x28
+#define PT_V9_G6 0x30
+#define PT_V9_G7 0x38
+#define PT_V9_I0 0x40
+#define PT_V9_I1 0x48
+#define PT_V9_I2 0x50
+#define PT_V9_I3 0x58
+#define PT_V9_I4 0x60
+#define PT_V9_I5 0x68
+#define PT_V9_I6 0x70
+#define PT_V9_FP PT_V9_I6
+#define PT_V9_I7 0x78
+#define PT_V9_TSTATE 0x80
+#define PT_V9_TPC 0x88
+#define PT_V9_TNPC 0x90
+#define PT_V9_Y 0x98
+#define PT_V9_MAGIC 0x9c
+#define PT_TSTATE PT_V9_TSTATE
+#define PT_TPC PT_V9_TPC
+#define PT_TNPC PT_V9_TNPC
+
+/* These for pt_regs32. */
+#define PT_PSR 0x0
+#define PT_PC 0x4
+#define PT_NPC 0x8
+#define PT_Y 0xc
+#define PT_G0 0x10
+#define PT_WIM PT_G0
+#define PT_G1 0x14
+#define PT_G2 0x18
+#define PT_G3 0x1c
+#define PT_G4 0x20
+#define PT_G5 0x24
+#define PT_G6 0x28
+#define PT_G7 0x2c
+#define PT_I0 0x30
+#define PT_I1 0x34
+#define PT_I2 0x38
+#define PT_I3 0x3c
+#define PT_I4 0x40
+#define PT_I5 0x44
+#define PT_I6 0x48
+#define PT_FP PT_I6
+#define PT_I7 0x4c
+
+/* Reg_window offsets */
+#define RW_V9_L0 0x00
+#define RW_V9_L1 0x08
+#define RW_V9_L2 0x10
+#define RW_V9_L3 0x18
+#define RW_V9_L4 0x20
+#define RW_V9_L5 0x28
+#define RW_V9_L6 0x30
+#define RW_V9_L7 0x38
+#define RW_V9_I0 0x40
+#define RW_V9_I1 0x48
+#define RW_V9_I2 0x50
+#define RW_V9_I3 0x58
+#define RW_V9_I4 0x60
+#define RW_V9_I5 0x68
+#define RW_V9_I6 0x70
+#define RW_V9_I7 0x78
+
+#define RW_L0 0x00
+#define RW_L1 0x04
+#define RW_L2 0x08
+#define RW_L3 0x0c
+#define RW_L4 0x10
+#define RW_L5 0x14
+#define RW_L6 0x18
+#define RW_L7 0x1c
+#define RW_I0 0x20
+#define RW_I1 0x24
+#define RW_I2 0x28
+#define RW_I3 0x2c
+#define RW_I4 0x30
+#define RW_I5 0x34
+#define RW_I6 0x38
+#define RW_I7 0x3c
+
+/* Stack_frame offsets */
+#define SF_V9_L0 0x00
+#define SF_V9_L1 0x08
+#define SF_V9_L2 0x10
+#define SF_V9_L3 0x18
+#define SF_V9_L4 0x20
+#define SF_V9_L5 0x28
+#define SF_V9_L6 0x30
+#define SF_V9_L7 0x38
+#define SF_V9_I0 0x40
+#define SF_V9_I1 0x48
+#define SF_V9_I2 0x50
+#define SF_V9_I3 0x58
+#define SF_V9_I4 0x60
+#define SF_V9_I5 0x68
+#define SF_V9_FP 0x70
+#define SF_V9_PC 0x78
+#define SF_V9_RETP 0x80
+#define SF_V9_XARG0 0x88
+#define SF_V9_XARG1 0x90
+#define SF_V9_XARG2 0x98
+#define SF_V9_XARG3 0xa0
+#define SF_V9_XARG4 0xa8
+#define SF_V9_XARG5 0xb0
+#define SF_V9_XXARG 0xb8
+
+#define SF_L0 0x00
+#define SF_L1 0x04
+#define SF_L2 0x08
+#define SF_L3 0x0c
+#define SF_L4 0x10
+#define SF_L5 0x14
+#define SF_L6 0x18
+#define SF_L7 0x1c
+#define SF_I0 0x20
+#define SF_I1 0x24
+#define SF_I2 0x28
+#define SF_I3 0x2c
+#define SF_I4 0x30
+#define SF_I5 0x34
+#define SF_FP 0x38
+#define SF_PC 0x3c
+#define SF_RETP 0x40
+#define SF_XARG0 0x44
+#define SF_XARG1 0x48
+#define SF_XARG2 0x4c
+#define SF_XARG3 0x50
+#define SF_XARG4 0x54
+#define SF_XARG5 0x58
+#define SF_XXARG 0x5c
+
+#ifdef __KERNEL__
+
+/* global_reg_snapshot offsets */
+#define GR_SNAP_TSTATE 0x00
+#define GR_SNAP_TPC 0x08
+#define GR_SNAP_TNPC 0x10
+#define GR_SNAP_O7 0x18
+#define GR_SNAP_I7 0x20
+#define GR_SNAP_RPC 0x28
+#define GR_SNAP_THREAD 0x30
+#define GR_SNAP_PAD1 0x38
+
+#endif /* __KERNEL__ */
+
+/* Stuff for the ptrace system call */
+#define PTRACE_SPARC_DETACH 11
+#define PTRACE_GETREGS 12
+#define PTRACE_SETREGS 13
+#define PTRACE_GETFPREGS 14
+#define PTRACE_SETFPREGS 15
+#define PTRACE_READDATA 16
+#define PTRACE_WRITEDATA 17
+#define PTRACE_READTEXT 18
+#define PTRACE_WRITETEXT 19
+#define PTRACE_GETFPAREGS 20
+#define PTRACE_SETFPAREGS 21
+
+/* There are for debugging 64-bit processes, either from a 32 or 64 bit
+ * parent. Thus their complements are for debugging 32-bit processes only.
+ */
+
+#define PTRACE_GETREGS64 22
+#define PTRACE_SETREGS64 23
+/* PTRACE_SYSCALL is 24 */
+#define PTRACE_GETFPREGS64 25
+#define PTRACE_SETFPREGS64 26
+
+#endif /* !(__SPARC_PTRACE_H) */
diff --git a/arch/sparc/include/asm/ptrace_32.h b/arch/sparc/include/asm/ptrace_32.h
deleted file mode 100644
index 4cef450167d..00000000000
--- a/arch/sparc/include/asm/ptrace_32.h
+++ /dev/null
@@ -1,186 +0,0 @@
-#ifndef _SPARC_PTRACE_H
-#define _SPARC_PTRACE_H
-
-#include <asm/psr.h>
-
-/* This struct defines the way the registers are stored on the
- * stack during a system call and basically all traps.
- */
-
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-
-struct pt_regs {
- unsigned long psr;
- unsigned long pc;
- unsigned long npc;
- unsigned long y;
- unsigned long u_regs[16]; /* globals and ins */
-};
-
-#define UREG_G0 0
-#define UREG_G1 1
-#define UREG_G2 2
-#define UREG_G3 3
-#define UREG_G4 4
-#define UREG_G5 5
-#define UREG_G6 6
-#define UREG_G7 7
-#define UREG_I0 8
-#define UREG_I1 9
-#define UREG_I2 10
-#define UREG_I3 11
-#define UREG_I4 12
-#define UREG_I5 13
-#define UREG_I6 14
-#define UREG_I7 15
-#define UREG_WIM UREG_G0
-#define UREG_FADDR UREG_G0
-#define UREG_FP UREG_I6
-#define UREG_RETPC UREG_I7
-
-/* A register window */
-struct reg_window {
- unsigned long locals[8];
- unsigned long ins[8];
-};
-
-/* A Sparc stack frame */
-struct sparc_stackf {
- unsigned long locals[8];
- unsigned long ins[6];
- struct sparc_stackf *fp;
- unsigned long callers_pc;
- char *structptr;
- unsigned long xargs[6];
- unsigned long xxargs[1];
-};
-
-#define TRACEREG_SZ sizeof(struct pt_regs)
-#define STACKFRAME_SZ sizeof(struct sparc_stackf)
-
-#ifdef __KERNEL__
-
-#include <asm/system.h>
-
-static inline bool pt_regs_is_syscall(struct pt_regs *regs)
-{
- return (regs->psr & PSR_SYSCALL);
-}
-
-static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
-{
- return (regs->psr &= ~PSR_SYSCALL);
-}
-
-#define arch_ptrace_stop_needed(exit_code, info) \
-({ flush_user_windows(); \
- current_thread_info()->w_saved != 0; \
-})
-
-#define arch_ptrace_stop(exit_code, info) \
- synchronize_user_stack()
-
-#define user_mode(regs) (!((regs)->psr & PSR_PS))
-#define instruction_pointer(regs) ((regs)->pc)
-#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
-unsigned long profile_pc(struct pt_regs *);
-extern void show_regs(struct pt_regs *);
-#endif
-
-#else /* __ASSEMBLY__ */
-/* For assembly code. */
-#define TRACEREG_SZ 0x50
-#define STACKFRAME_SZ 0x60
-#endif
-
-/*
- * The asm-offsets.h is a generated file, so we cannot include it.
- * It may be OK for glibc headers, but it's utterly pointless for C code.
- * The assembly code using those offsets has to include it explicitly.
- */
-/* #include <asm/asm-offsets.h> */
-
-/* These are for pt_regs. */
-#define PT_PSR 0x0
-#define PT_PC 0x4
-#define PT_NPC 0x8
-#define PT_Y 0xc
-#define PT_G0 0x10
-#define PT_WIM PT_G0
-#define PT_G1 0x14
-#define PT_G2 0x18
-#define PT_G3 0x1c
-#define PT_G4 0x20
-#define PT_G5 0x24
-#define PT_G6 0x28
-#define PT_G7 0x2c
-#define PT_I0 0x30
-#define PT_I1 0x34
-#define PT_I2 0x38
-#define PT_I3 0x3c
-#define PT_I4 0x40
-#define PT_I5 0x44
-#define PT_I6 0x48
-#define PT_FP PT_I6
-#define PT_I7 0x4c
-
-/* Reg_window offsets */
-#define RW_L0 0x00
-#define RW_L1 0x04
-#define RW_L2 0x08
-#define RW_L3 0x0c
-#define RW_L4 0x10
-#define RW_L5 0x14
-#define RW_L6 0x18
-#define RW_L7 0x1c
-#define RW_I0 0x20
-#define RW_I1 0x24
-#define RW_I2 0x28
-#define RW_I3 0x2c
-#define RW_I4 0x30
-#define RW_I5 0x34
-#define RW_I6 0x38
-#define RW_I7 0x3c
-
-/* Stack_frame offsets */
-#define SF_L0 0x00
-#define SF_L1 0x04
-#define SF_L2 0x08
-#define SF_L3 0x0c
-#define SF_L4 0x10
-#define SF_L5 0x14
-#define SF_L6 0x18
-#define SF_L7 0x1c
-#define SF_I0 0x20
-#define SF_I1 0x24
-#define SF_I2 0x28
-#define SF_I3 0x2c
-#define SF_I4 0x30
-#define SF_I5 0x34
-#define SF_FP 0x38
-#define SF_PC 0x3c
-#define SF_RETP 0x40
-#define SF_XARG0 0x44
-#define SF_XARG1 0x48
-#define SF_XARG2 0x4c
-#define SF_XARG3 0x50
-#define SF_XARG4 0x54
-#define SF_XARG5 0x58
-#define SF_XXARG 0x5c
-
-/* Stuff for the ptrace system call */
-#define PTRACE_SPARC_DETACH 11
-#define PTRACE_GETREGS 12
-#define PTRACE_SETREGS 13
-#define PTRACE_GETFPREGS 14
-#define PTRACE_SETFPREGS 15
-#define PTRACE_READDATA 16
-#define PTRACE_WRITEDATA 17
-#define PTRACE_READTEXT 18
-#define PTRACE_WRITETEXT 19
-#define PTRACE_GETFPAREGS 20
-#define PTRACE_SETFPAREGS 21
-
-#endif /* !(_SPARC_PTRACE_H) */
diff --git a/arch/sparc/include/asm/ptrace_64.h b/arch/sparc/include/asm/ptrace_64.h
deleted file mode 100644
index cd6fbfc2043..00000000000
--- a/arch/sparc/include/asm/ptrace_64.h
+++ /dev/null
@@ -1,356 +0,0 @@
-#ifndef _SPARC64_PTRACE_H
-#define _SPARC64_PTRACE_H
-
-#include <asm/pstate.h>
-
-/* This struct defines the way the registers are stored on the
- * stack during a system call and basically all traps.
- */
-
-/* This magic value must have the low 9 bits clear,
- * as that is where we encode the %tt value, see below.
- */
-#define PT_REGS_MAGIC 0x57ac6c00
-
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-
-struct pt_regs {
- unsigned long u_regs[16]; /* globals and ins */
- unsigned long tstate;
- unsigned long tpc;
- unsigned long tnpc;
- unsigned int y;
-
- /* We encode a magic number, PT_REGS_MAGIC, along
- * with the %tt (trap type) register value at trap
- * entry time. The magic number allows us to identify
- * accurately a trap stack frame in the stack
- * unwinder, and the %tt value allows us to test
- * things like "in a system call" etc. for an arbitray
- * process.
- *
- * The PT_REGS_MAGIC is choosen such that it can be
- * loaded completely using just a sethi instruction.
- */
- unsigned int magic;
-};
-
-struct pt_regs32 {
- unsigned int psr;
- unsigned int pc;
- unsigned int npc;
- unsigned int y;
- unsigned int u_regs[16]; /* globals and ins */
-};
-
-#define UREG_G0 0
-#define UREG_G1 1
-#define UREG_G2 2
-#define UREG_G3 3
-#define UREG_G4 4
-#define UREG_G5 5
-#define UREG_G6 6
-#define UREG_G7 7
-#define UREG_I0 8
-#define UREG_I1 9
-#define UREG_I2 10
-#define UREG_I3 11
-#define UREG_I4 12
-#define UREG_I5 13
-#define UREG_I6 14
-#define UREG_I7 15
-#define UREG_FP UREG_I6
-#define UREG_RETPC UREG_I7
-
-/* A V9 register window */
-struct reg_window {
- unsigned long locals[8];
- unsigned long ins[8];
-};
-
-/* A 32-bit register window. */
-struct reg_window32 {
- unsigned int locals[8];
- unsigned int ins[8];
-};
-
-/* A V9 Sparc stack frame */
-struct sparc_stackf {
- unsigned long locals[8];
- unsigned long ins[6];
- struct sparc_stackf *fp;
- unsigned long callers_pc;
- char *structptr;
- unsigned long xargs[6];
- unsigned long xxargs[1];
-};
-
-/* A 32-bit Sparc stack frame */
-struct sparc_stackf32 {
- unsigned int locals[8];
- unsigned int ins[6];
- unsigned int fp;
- unsigned int callers_pc;
- unsigned int structptr;
- unsigned int xargs[6];
- unsigned int xxargs[1];
-};
-
-struct sparc_trapf {
- unsigned long locals[8];
- unsigned long ins[8];
- unsigned long _unused;
- struct pt_regs *regs;
-};
-
-#define TRACEREG_SZ sizeof(struct pt_regs)
-#define STACKFRAME_SZ sizeof(struct sparc_stackf)
-
-#define TRACEREG32_SZ sizeof(struct pt_regs32)
-#define STACKFRAME32_SZ sizeof(struct sparc_stackf32)
-
-#ifdef __KERNEL__
-
-#include <linux/threads.h>
-#include <asm/system.h>
-
-static inline int pt_regs_trap_type(struct pt_regs *regs)
-{
- return regs->magic & 0x1ff;
-}
-
-static inline bool pt_regs_is_syscall(struct pt_regs *regs)
-{
- return (regs->tstate & TSTATE_SYSCALL);
-}
-
-static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
-{
- return (regs->tstate &= ~TSTATE_SYSCALL);
-}
-
-#define arch_ptrace_stop_needed(exit_code, info) \
-({ flush_user_windows(); \
- get_thread_wsaved() != 0; \
-})
-
-#define arch_ptrace_stop(exit_code, info) \
- synchronize_user_stack()
-
-struct global_reg_snapshot {
- unsigned long tstate;
- unsigned long tpc;
- unsigned long tnpc;
- unsigned long o7;
- unsigned long i7;
- unsigned long rpc;
- struct thread_info *thread;
- unsigned long pad1;
-};
-extern struct global_reg_snapshot global_reg_snapshot[NR_CPUS];
-
-#define force_successful_syscall_return() \
-do { current_thread_info()->syscall_noerror = 1; \
-} while (0)
-#define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
-#define instruction_pointer(regs) ((regs)->tpc)
-#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
-#define regs_return_value(regs) ((regs)->u_regs[UREG_I0])
-#ifdef CONFIG_SMP
-extern unsigned long profile_pc(struct pt_regs *);
-#else
-#define profile_pc(regs) instruction_pointer(regs)
-#endif
-extern void show_regs(struct pt_regs *);
-#endif
-
-#else /* __ASSEMBLY__ */
-/* For assembly code. */
-#define TRACEREG_SZ 0xa0
-#define STACKFRAME_SZ 0xc0
-
-#define TRACEREG32_SZ 0x50
-#define STACKFRAME32_SZ 0x60
-#endif
-
-#ifdef __KERNEL__
-#define STACK_BIAS 2047
-#endif
-
-/* These are for pt_regs. */
-#define PT_V9_G0 0x00
-#define PT_V9_G1 0x08
-#define PT_V9_G2 0x10
-#define PT_V9_G3 0x18
-#define PT_V9_G4 0x20
-#define PT_V9_G5 0x28
-#define PT_V9_G6 0x30
-#define PT_V9_G7 0x38
-#define PT_V9_I0 0x40
-#define PT_V9_I1 0x48
-#define PT_V9_I2 0x50
-#define PT_V9_I3 0x58
-#define PT_V9_I4 0x60
-#define PT_V9_I5 0x68
-#define PT_V9_I6 0x70
-#define PT_V9_FP PT_V9_I6
-#define PT_V9_I7 0x78
-#define PT_V9_TSTATE 0x80
-#define PT_V9_TPC 0x88
-#define PT_V9_TNPC 0x90
-#define PT_V9_Y 0x98
-#define PT_V9_MAGIC 0x9c
-#define PT_TSTATE PT_V9_TSTATE
-#define PT_TPC PT_V9_TPC
-#define PT_TNPC PT_V9_TNPC
-
-/* These for pt_regs32. */
-#define PT_PSR 0x0
-#define PT_PC 0x4
-#define PT_NPC 0x8
-#define PT_Y 0xc
-#define PT_G0 0x10
-#define PT_WIM PT_G0
-#define PT_G1 0x14
-#define PT_G2 0x18
-#define PT_G3 0x1c
-#define PT_G4 0x20
-#define PT_G5 0x24
-#define PT_G6 0x28
-#define PT_G7 0x2c
-#define PT_I0 0x30
-#define PT_I1 0x34
-#define PT_I2 0x38
-#define PT_I3 0x3c
-#define PT_I4 0x40
-#define PT_I5 0x44
-#define PT_I6 0x48
-#define PT_FP PT_I6
-#define PT_I7 0x4c
-
-/* Reg_window offsets */
-#define RW_V9_L0 0x00
-#define RW_V9_L1 0x08
-#define RW_V9_L2 0x10
-#define RW_V9_L3 0x18
-#define RW_V9_L4 0x20
-#define RW_V9_L5 0x28
-#define RW_V9_L6 0x30
-#define RW_V9_L7 0x38
-#define RW_V9_I0 0x40
-#define RW_V9_I1 0x48
-#define RW_V9_I2 0x50
-#define RW_V9_I3 0x58
-#define RW_V9_I4 0x60
-#define RW_V9_I5 0x68
-#define RW_V9_I6 0x70
-#define RW_V9_I7 0x78
-
-#define RW_L0 0x00
-#define RW_L1 0x04
-#define RW_L2 0x08
-#define RW_L3 0x0c
-#define RW_L4 0x10
-#define RW_L5 0x14
-#define RW_L6 0x18
-#define RW_L7 0x1c
-#define RW_I0 0x20
-#define RW_I1 0x24
-#define RW_I2 0x28
-#define RW_I3 0x2c
-#define RW_I4 0x30
-#define RW_I5 0x34
-#define RW_I6 0x38
-#define RW_I7 0x3c
-
-/* Stack_frame offsets */
-#define SF_V9_L0 0x00
-#define SF_V9_L1 0x08
-#define SF_V9_L2 0x10
-#define SF_V9_L3 0x18
-#define SF_V9_L4 0x20
-#define SF_V9_L5 0x28
-#define SF_V9_L6 0x30
-#define SF_V9_L7 0x38
-#define SF_V9_I0 0x40
-#define SF_V9_I1 0x48
-#define SF_V9_I2 0x50
-#define SF_V9_I3 0x58
-#define SF_V9_I4 0x60
-#define SF_V9_I5 0x68
-#define SF_V9_FP 0x70
-#define SF_V9_PC 0x78
-#define SF_V9_RETP 0x80
-#define SF_V9_XARG0 0x88
-#define SF_V9_XARG1 0x90
-#define SF_V9_XARG2 0x98
-#define SF_V9_XARG3 0xa0
-#define SF_V9_XARG4 0xa8
-#define SF_V9_XARG5 0xb0
-#define SF_V9_XXARG 0xb8
-
-#define SF_L0 0x00
-#define SF_L1 0x04
-#define SF_L2 0x08
-#define SF_L3 0x0c
-#define SF_L4 0x10
-#define SF_L5 0x14
-#define SF_L6 0x18
-#define SF_L7 0x1c
-#define SF_I0 0x20
-#define SF_I1 0x24
-#define SF_I2 0x28
-#define SF_I3 0x2c
-#define SF_I4 0x30
-#define SF_I5 0x34
-#define SF_FP 0x38
-#define SF_PC 0x3c
-#define SF_RETP 0x40
-#define SF_XARG0 0x44
-#define SF_XARG1 0x48
-#define SF_XARG2 0x4c
-#define SF_XARG3 0x50
-#define SF_XARG4 0x54
-#define SF_XARG5 0x58
-#define SF_XXARG 0x5c
-
-#ifdef __KERNEL__
-
-/* global_reg_snapshot offsets */
-#define GR_SNAP_TSTATE 0x00
-#define GR_SNAP_TPC 0x08
-#define GR_SNAP_TNPC 0x10
-#define GR_SNAP_O7 0x18
-#define GR_SNAP_I7 0x20
-#define GR_SNAP_RPC 0x28
-#define GR_SNAP_THREAD 0x30
-#define GR_SNAP_PAD1 0x38
-
-#endif /* __KERNEL__ */
-
-/* Stuff for the ptrace system call */
-#define PTRACE_SPARC_DETACH 11
-#define PTRACE_GETREGS 12
-#define PTRACE_SETREGS 13
-#define PTRACE_GETFPREGS 14
-#define PTRACE_SETFPREGS 15
-#define PTRACE_READDATA 16
-#define PTRACE_WRITEDATA 17
-#define PTRACE_READTEXT 18
-#define PTRACE_WRITETEXT 19
-#define PTRACE_GETFPAREGS 20
-#define PTRACE_SETFPAREGS 21
-
-/* There are for debugging 64-bit processes, either from a 32 or 64 bit
- * parent. Thus their complements are for debugging 32-bit processes only.
- */
-
-#define PTRACE_GETREGS64 22
-#define PTRACE_SETREGS64 23
-/* PTRACE_SYSCALL is 24 */
-#define PTRACE_GETFPREGS64 25
-#define PTRACE_SETFPREGS64 26
-
-#endif /* !(_SPARC64_PTRACE_H) */
diff --git a/arch/sparc/include/asm/reg.h b/arch/sparc/include/asm/reg.h
deleted file mode 100644
index 0c16e19cae4..00000000000
--- a/arch/sparc/include/asm/reg.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef ___ASM_SPARC_REG_H
-#define ___ASM_SPARC_REG_H
-#if defined(__sparc__) && defined(__arch64__)
-#include <asm/reg_64.h>
-#else
-#include <asm/reg_32.h>
-#endif
-#endif
diff --git a/arch/sparc/include/asm/reg_32.h b/arch/sparc/include/asm/reg_32.h
deleted file mode 100644
index 1efb056fb3d..00000000000
--- a/arch/sparc/include/asm/reg_32.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * linux/include/asm/reg.h
- * Layout of the registers as expected by gdb on the Sparc
- * we should replace the user.h definitions with those in
- * this file, we don't even use the other
- * -miguel
- *
- * The names of the structures, constants and aliases in this file
- * have the same names as the sunos ones, some programs rely on these
- * names (gdb for example).
- *
- */
-
-#ifndef __SPARC_REG_H
-#define __SPARC_REG_H
-
-struct regs {
- int r_psr;
-#define r_ps r_psr
- int r_pc;
- int r_npc;
- int r_y;
- int r_g1;
- int r_g2;
- int r_g3;
- int r_g4;
- int r_g5;
- int r_g6;
- int r_g7;
- int r_o0;
- int r_o1;
- int r_o2;
- int r_o3;
- int r_o4;
- int r_o5;
- int r_o6;
- int r_o7;
-};
-
-struct fpq {
- unsigned long *addr;
- unsigned long instr;
-};
-
-struct fq {
- union {
- double whole;
- struct fpq fpq;
- } FQu;
-};
-
-#define FPU_REGS_TYPE unsigned int
-#define FPU_FSR_TYPE unsigned
-
-struct fp_status {
- union {
- FPU_REGS_TYPE Fpu_regs[32];
- double Fpu_dregs[16];
- } fpu_fr;
- FPU_FSR_TYPE Fpu_fsr;
- unsigned Fpu_flags;
- unsigned Fpu_extra;
- unsigned Fpu_qcnt;
- struct fq Fpu_q[16];
-};
-
-#define fpu_regs f_fpstatus.fpu_fr.Fpu_regs
-#define fpu_dregs f_fpstatus.fpu_fr.Fpu_dregs
-#define fpu_fsr f_fpstatus.Fpu_fsr
-#define fpu_flags f_fpstatus.Fpu_flags
-#define fpu_extra f_fpstatus.Fpu_extra
-#define fpu_q f_fpstatus.Fpu_q
-#define fpu_qcnt f_fpstatus.Fpu_qcnt
-
-struct fpu {
- struct fp_status f_fpstatus;
-};
-
-#endif /* __SPARC_REG_H */
diff --git a/arch/sparc/include/asm/reg_64.h b/arch/sparc/include/asm/reg_64.h
deleted file mode 100644
index 6f277d7c7d8..00000000000
--- a/arch/sparc/include/asm/reg_64.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * linux/asm/reg.h
- * Layout of the registers as expected by gdb on the Sparc
- * we should replace the user.h definitions with those in
- * this file, we don't even use the other
- * -miguel
- *
- * The names of the structures, constants and aliases in this file
- * have the same names as the sunos ones, some programs rely on these
- * names (gdb for example).
- *
- */
-
-#ifndef __SPARC64_REG_H
-#define __SPARC64_REG_H
-
-struct regs {
- unsigned long r_g1;
- unsigned long r_g2;
- unsigned long r_g3;
- unsigned long r_g4;
- unsigned long r_g5;
- unsigned long r_g6;
- unsigned long r_g7;
- unsigned long r_o0;
- unsigned long r_o1;
- unsigned long r_o2;
- unsigned long r_o3;
- unsigned long r_o4;
- unsigned long r_o5;
- unsigned long r_o6;
- unsigned long r_o7;
- unsigned long __pad;
- unsigned long r_tstate;
- unsigned long r_tpc;
- unsigned long r_tnpc;
- unsigned int r_y;
- unsigned int r_fprs;
-};
-
-#define FPU_REGS_TYPE unsigned int
-#define FPU_FSR_TYPE unsigned long
-
-struct fp_status {
- unsigned long fpu_fr[32];
- unsigned long Fpu_fsr;
-};
-
-struct fpu {
- struct fp_status f_fpstatus;
-};
-
-#define fpu_regs f_fpstatus.fpu_fr
-#define fpu_fsr f_fpstatus.Fpu_fsr
-
-#endif /* __SPARC64_REG_H */
diff --git a/arch/sparc/include/asm/sigcontext.h b/arch/sparc/include/asm/sigcontext.h
index e92de7e286b..a1607d18035 100644
--- a/arch/sparc/include/asm/sigcontext.h
+++ b/arch/sparc/include/asm/sigcontext.h
@@ -1,8 +1,96 @@
-#ifndef ___ASM_SPARC_SIGCONTEXT_H
-#define ___ASM_SPARC_SIGCONTEXT_H
-#if defined(__sparc__) && defined(__arch64__)
-#include <asm/sigcontext_64.h>
+#ifndef __SPARC_SIGCONTEXT_H
+#define __SPARC_SIGCONTEXT_H
+
+#ifdef __KERNEL__
+#include <asm/ptrace.h>
+
+#ifndef __ASSEMBLY__
+
+#define __SUNOS_MAXWIN 31
+
+/* This is what SunOS does, so shall I unless we use new 32bit signals or rt signals. */
+struct sigcontext32 {
+ int sigc_onstack; /* state to restore */
+ int sigc_mask; /* sigmask to restore */
+ int sigc_sp; /* stack pointer */
+ int sigc_pc; /* program counter */
+ int sigc_npc; /* next program counter */
+ int sigc_psr; /* for condition codes etc */
+ int sigc_g1; /* User uses these two registers */
+ int sigc_o0; /* within the trampoline code. */
+
+ /* Now comes information regarding the users window set
+ * at the time of the signal.
+ */
+ int sigc_oswins; /* outstanding windows */
+
+ /* stack ptrs for each regwin buf */
+ unsigned sigc_spbuf[__SUNOS_MAXWIN];
+
+ /* Windows to restore after signal */
+ struct reg_window32 sigc_wbuf[__SUNOS_MAXWIN];
+};
+
+
+/* This is what we use for 32bit new non-rt signals. */
+
+typedef struct {
+ struct {
+ unsigned int psr;
+ unsigned int pc;
+ unsigned int npc;
+ unsigned int y;
+ unsigned int u_regs[16]; /* globals and ins */
+ } si_regs;
+ int si_mask;
+} __siginfo32_t;
+
+#ifdef CONFIG_SPARC64
+typedef struct {
+ unsigned int si_float_regs [64];
+ unsigned long si_fsr;
+ unsigned long si_gsr;
+ unsigned long si_fprs;
+} __siginfo_fpu_t;
+
+/* This is what SunOS doesn't, so we have to write this alone
+ and do it properly. */
+struct sigcontext {
+ /* The size of this array has to match SI_MAX_SIZE from siginfo.h */
+ char sigc_info[128];
+ struct {
+ unsigned long u_regs[16]; /* globals and ins */
+ unsigned long tstate;
+ unsigned long tpc;
+ unsigned long tnpc;
+ unsigned int y;
+ unsigned int fprs;
+ } sigc_regs;
+ __siginfo_fpu_t * sigc_fpu_save;
+ struct {
+ void * ss_sp;
+ int ss_flags;
+ unsigned long ss_size;
+ } sigc_stack;
+ unsigned long sigc_mask;
+};
+
#else
-#include <asm/sigcontext_32.h>
-#endif
-#endif
+
+typedef struct {
+ unsigned long si_float_regs [32];
+ unsigned long si_fsr;
+ unsigned long si_fpqdepth;
+ struct {
+ unsigned long *insn_addr;
+ unsigned long insn;
+ } si_fpqueue [16];
+} __siginfo_fpu_t;
+#endif /* (CONFIG_SPARC64) */
+
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* (__KERNEL__) */
+
+#endif /* !(__SPARC_SIGCONTEXT_H) */
diff --git a/arch/sparc/include/asm/sigcontext_32.h b/arch/sparc/include/asm/sigcontext_32.h
deleted file mode 100644
index c5fb60dcbd7..00000000000
--- a/arch/sparc/include/asm/sigcontext_32.h
+++ /dev/null
@@ -1,62 +0,0 @@
-#ifndef __SPARC_SIGCONTEXT_H
-#define __SPARC_SIGCONTEXT_H
-
-#ifdef __KERNEL__
-#include <asm/ptrace.h>
-
-#ifndef __ASSEMBLY__
-
-#define __SUNOS_MAXWIN 31
-
-/* This is what SunOS does, so shall I. */
-struct sigcontext {
- int sigc_onstack; /* state to restore */
- int sigc_mask; /* sigmask to restore */
- int sigc_sp; /* stack pointer */
- int sigc_pc; /* program counter */
- int sigc_npc; /* next program counter */
- int sigc_psr; /* for condition codes etc */
- int sigc_g1; /* User uses these two registers */
- int sigc_o0; /* within the trampoline code. */
-
- /* Now comes information regarding the users window set
- * at the time of the signal.
- */
- int sigc_oswins; /* outstanding windows */
-
- /* stack ptrs for each regwin buf */
- char *sigc_spbuf[__SUNOS_MAXWIN];
-
- /* Windows to restore after signal */
- struct {
- unsigned long locals[8];
- unsigned long ins[8];
- } sigc_wbuf[__SUNOS_MAXWIN];
-};
-
-typedef struct {
- struct {
- unsigned long psr;
- unsigned long pc;
- unsigned long npc;
- unsigned long y;
- unsigned long u_regs[16]; /* globals and ins */
- } si_regs;
- int si_mask;
-} __siginfo_t;
-
-typedef struct {
- unsigned long si_float_regs [32];
- unsigned long si_fsr;
- unsigned long si_fpqdepth;
- struct {
- unsigned long *insn_addr;
- unsigned long insn;
- } si_fpqueue [16];
-} __siginfo_fpu_t;
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* (__KERNEL__) */
-
-#endif /* !(__SPARC_SIGCONTEXT_H) */
diff --git a/arch/sparc/include/asm/sigcontext_64.h b/arch/sparc/include/asm/sigcontext_64.h
deleted file mode 100644
index 1c868d680cf..00000000000
--- a/arch/sparc/include/asm/sigcontext_64.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#ifndef __SPARC64_SIGCONTEXT_H
-#define __SPARC64_SIGCONTEXT_H
-
-#ifdef __KERNEL__
-#include <asm/ptrace.h>
-#endif
-
-#ifndef __ASSEMBLY__
-
-#ifdef __KERNEL__
-
-#define __SUNOS_MAXWIN 31
-
-/* This is what SunOS does, so shall I unless we use new 32bit signals or rt signals. */
-struct sigcontext32 {
- int sigc_onstack; /* state to restore */
- int sigc_mask; /* sigmask to restore */
- int sigc_sp; /* stack pointer */
- int sigc_pc; /* program counter */
- int sigc_npc; /* next program counter */
- int sigc_psr; /* for condition codes etc */
- int sigc_g1; /* User uses these two registers */
- int sigc_o0; /* within the trampoline code. */
-
- /* Now comes information regarding the users window set
- * at the time of the signal.
- */
- int sigc_oswins; /* outstanding windows */
-
- /* stack ptrs for each regwin buf */
- unsigned sigc_spbuf[__SUNOS_MAXWIN];
-
- /* Windows to restore after signal */
- struct reg_window32 sigc_wbuf[__SUNOS_MAXWIN];
-};
-
-#endif
-
-#ifdef __KERNEL__
-
-/* This is what we use for 32bit new non-rt signals. */
-
-typedef struct {
- struct {
- unsigned int psr;
- unsigned int pc;
- unsigned int npc;
- unsigned int y;
- unsigned int u_regs[16]; /* globals and ins */
- } si_regs;
- int si_mask;
-} __siginfo32_t;
-
-#endif
-
-typedef struct {
- unsigned int si_float_regs [64];
- unsigned long si_fsr;
- unsigned long si_gsr;
- unsigned long si_fprs;
-} __siginfo_fpu_t;
-
-/* This is what SunOS doesn't, so we have to write this alone
- and do it properly. */
-struct sigcontext {
- /* The size of this array has to match SI_MAX_SIZE from siginfo.h */
- char sigc_info[128];
- struct {
- unsigned long u_regs[16]; /* globals and ins */
- unsigned long tstate;
- unsigned long tpc;
- unsigned long tnpc;
- unsigned int y;
- unsigned int fprs;
- } sigc_regs;
- __siginfo_fpu_t * sigc_fpu_save;
- struct {
- void * ss_sp;
- int ss_flags;
- unsigned long ss_size;
- } sigc_stack;
- unsigned long sigc_mask;
-};
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(__SPARC64_SIGCONTEXT_H) */
diff --git a/arch/sparc/include/asm/siginfo.h b/arch/sparc/include/asm/siginfo.h
index bd81f8d7f5c..988e5d8ed11 100644
--- a/arch/sparc/include/asm/siginfo.h
+++ b/arch/sparc/include/asm/siginfo.h
@@ -1,8 +1,37 @@
-#ifndef ___ASM_SPARC_SIGINFO_H
-#define ___ASM_SPARC_SIGINFO_H
+#ifndef __SPARC_SIGINFO_H
+#define __SPARC_SIGINFO_H
+
#if defined(__sparc__) && defined(__arch64__)
-#include <asm/siginfo_64.h>
-#else
-#include <asm/siginfo_32.h>
-#endif
-#endif
+
+#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
+#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
+#define __ARCH_SI_BAND_T int
+
+#endif /* defined(__sparc__) && defined(__arch64__) */
+
+
+#define __ARCH_SI_TRAPNO
+
+#include <asm-generic/siginfo.h>
+
+#ifdef __KERNEL__
+
+#include <linux/compat.h>
+
+#ifdef CONFIG_COMPAT
+
+struct compat_siginfo;
+
+#endif /* CONFIG_COMPAT */
+
+#endif /* __KERNEL__ */
+
+#define SI_NOINFO 32767 /* no information in siginfo_t */
+
+/*
+ * SIGEMT si_codes
+ */
+#define EMT_TAGOVF (__SI_FAULT|1) /* tag overflow */
+#define NSIGEMT 1
+
+#endif /* !(__SPARC_SIGINFO_H) */
diff --git a/arch/sparc/include/asm/siginfo_32.h b/arch/sparc/include/asm/siginfo_32.h
deleted file mode 100644
index 3c71af135c5..00000000000
--- a/arch/sparc/include/asm/siginfo_32.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef _SPARC_SIGINFO_H
-#define _SPARC_SIGINFO_H
-
-#define __ARCH_SI_UID_T unsigned int
-#define __ARCH_SI_TRAPNO
-
-#include <asm-generic/siginfo.h>
-
-#define SI_NOINFO 32767 /* no information in siginfo_t */
-
-/*
- * SIGEMT si_codes
- */
-#define EMT_TAGOVF (__SI_FAULT|1) /* tag overflow */
-#define NSIGEMT 1
-
-#endif /* !(_SPARC_SIGINFO_H) */
diff --git a/arch/sparc/include/asm/siginfo_64.h b/arch/sparc/include/asm/siginfo_64.h
deleted file mode 100644
index c96e6c30f8b..00000000000
--- a/arch/sparc/include/asm/siginfo_64.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef _SPARC64_SIGINFO_H
-#define _SPARC64_SIGINFO_H
-
-#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
-
-#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
-#define __ARCH_SI_TRAPNO
-#define __ARCH_SI_BAND_T int
-
-#include <asm-generic/siginfo.h>
-
-#ifdef __KERNEL__
-
-#include <linux/compat.h>
-
-#ifdef CONFIG_COMPAT
-
-struct compat_siginfo;
-
-#endif /* CONFIG_COMPAT */
-
-#endif /* __KERNEL__ */
-
-#define SI_NOINFO 32767 /* no information in siginfo_t */
-
-/*
- * SIGEMT si_codes
- */
-#define EMT_TAGOVF (__SI_FAULT|1) /* tag overflow */
-#define NSIGEMT 1
-
-#endif
diff --git a/arch/sparc/include/asm/signal.h b/arch/sparc/include/asm/signal.h
index 27ab05dc203..41535e77b25 100644
--- a/arch/sparc/include/asm/signal.h
+++ b/arch/sparc/include/asm/signal.h
@@ -1,8 +1,210 @@
-#ifndef ___ASM_SPARC_SIGNAL_H
-#define ___ASM_SPARC_SIGNAL_H
-#if defined(__sparc__) && defined(__arch64__)
-#include <asm/signal_64.h>
+#ifndef __SPARC_SIGNAL_H
+#define __SPARC_SIGNAL_H
+
+#include <asm/sigcontext.h>
+#include <linux/compiler.h>
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+#include <linux/personality.h>
+#include <linux/types.h>
+#endif
+#endif
+
+/* On the Sparc the signal handlers get passed a 'sub-signal' code
+ * for certain signal types, which we document here.
+ */
+#define SIGHUP 1
+#define SIGINT 2
+#define SIGQUIT 3
+#define SIGILL 4
+#define SUBSIG_STACK 0
+#define SUBSIG_ILLINST 2
+#define SUBSIG_PRIVINST 3
+#define SUBSIG_BADTRAP(t) (0x80 + (t))
+
+#define SIGTRAP 5
+#define SIGABRT 6
+#define SIGIOT 6
+
+#define SIGEMT 7
+#define SUBSIG_TAG 10
+
+#define SIGFPE 8
+#define SUBSIG_FPDISABLED 0x400
+#define SUBSIG_FPERROR 0x404
+#define SUBSIG_FPINTOVFL 0x001
+#define SUBSIG_FPSTSIG 0x002
+#define SUBSIG_IDIVZERO 0x014
+#define SUBSIG_FPINEXACT 0x0c4
+#define SUBSIG_FPDIVZERO 0x0c8
+#define SUBSIG_FPUNFLOW 0x0cc
+#define SUBSIG_FPOPERROR 0x0d0
+#define SUBSIG_FPOVFLOW 0x0d4
+
+#define SIGKILL 9
+#define SIGBUS 10
+#define SUBSIG_BUSTIMEOUT 1
+#define SUBSIG_ALIGNMENT 2
+#define SUBSIG_MISCERROR 5
+
+#define SIGSEGV 11
+#define SUBSIG_NOMAPPING 3
+#define SUBSIG_PROTECTION 4
+#define SUBSIG_SEGERROR 5
+
+#define SIGSYS 12
+
+#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGTERM 15
+#define SIGURG 16
+
+/* SunOS values which deviate from the Linux/i386 ones */
+#define SIGSTOP 17
+#define SIGTSTP 18
+#define SIGCONT 19
+#define SIGCHLD 20
+#define SIGTTIN 21
+#define SIGTTOU 22
+#define SIGIO 23
+#define SIGPOLL SIGIO /* SysV name for SIGIO */
+#define SIGXCPU 24
+#define SIGXFSZ 25
+#define SIGVTALRM 26
+#define SIGPROF 27
+#define SIGWINCH 28
+#define SIGLOST 29
+#define SIGPWR SIGLOST
+#define SIGUSR1 30
+#define SIGUSR2 31
+
+/* Most things should be clean enough to redefine this at will, if care
+ is taken to make libc match. */
+
+#define __OLD_NSIG 32
+#define __NEW_NSIG 64
+#define _NSIG_BPW 64
+#define _NSIG_WORDS (__NEW_NSIG / _NSIG_BPW)
+
+#define SIGRTMIN 32
+#define SIGRTMAX __NEW_NSIG
+
+#if defined(__KERNEL__) || defined(__WANT_POSIX1B_SIGNALS__)
+#define _NSIG __NEW_NSIG
+#define __new_sigset_t sigset_t
+#define __new_sigaction sigaction
+#define __new_sigaction32 sigaction32
+#define __old_sigset_t old_sigset_t
+#define __old_sigaction old_sigaction
+#define __old_sigaction32 old_sigaction32
#else
-#include <asm/signal_32.h>
+#define _NSIG __OLD_NSIG
+#define NSIG _NSIG
+#define __old_sigset_t sigset_t
+#define __old_sigaction sigaction
+#define __old_sigaction32 sigaction32
#endif
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned long __old_sigset_t; /* at least 32 bits */
+
+typedef struct {
+ unsigned long sig[_NSIG_WORDS];
+} __new_sigset_t;
+
+/* A SunOS sigstack */
+struct sigstack {
+ /* XXX 32-bit pointers pinhead XXX */
+ char *the_stack;
+ int cur_status;
+};
+
+/* Sigvec flags */
+#define _SV_SSTACK 1u /* This signal handler should use sig-stack */
+#define _SV_INTR 2u /* Sig return should not restart system call */
+#define _SV_RESET 4u /* Set handler to SIG_DFL upon taken signal */
+#define _SV_IGNCHILD 8u /* Do not send SIGCHLD */
+
+/*
+ * sa_flags values: SA_STACK is not currently supported, but will allow the
+ * usage of signal stacks by using the (now obsolete) sa_restorer field in
+ * the sigaction structure as a stack pointer. This is now possible due to
+ * the changes in signal handling. LBT 010493.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ */
+#define SA_NOCLDSTOP _SV_IGNCHILD
+#define SA_STACK _SV_SSTACK
+#define SA_ONSTACK _SV_SSTACK
+#define SA_RESTART _SV_INTR
+#define SA_ONESHOT _SV_RESET
+#define SA_NOMASK 0x20u
+#define SA_NOCLDWAIT 0x100u
+#define SA_SIGINFO 0x200u
+
+
+#define SIG_BLOCK 0x01 /* for blocking signals */
+#define SIG_UNBLOCK 0x02 /* for unblocking signals */
+#define SIG_SETMASK 0x04 /* for setting the signal mask */
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK 1
+#define SS_DISABLE 2
+
+#define MINSIGSTKSZ 4096
+#define SIGSTKSZ 16384
+
+#ifdef __KERNEL__
+/*
+ * DJHR
+ * SA_STATIC_ALLOC is used for the sparc32 system to indicate that this
+ * interrupt handler's irq structure should be statically allocated
+ * by the request_irq routine.
+ * The alternative is that arch/sparc/kernel/irq.c has carnal knowledge
+ * of interrupt usage and that sucks. Also without a flag like this
+ * it may be possible for the free_irq routine to attempt to free
+ * statically allocated data.. which is NOT GOOD.
+ *
+ */
+#define SA_STATIC_ALLOC 0x8000
#endif
+
+#include <asm-generic/signal.h>
+
+struct __new_sigaction {
+ __sighandler_t sa_handler;
+ unsigned long sa_flags;
+ __sigrestore_t sa_restorer; /* not used by Linux/SPARC yet */
+ __new_sigset_t sa_mask;
+};
+
+struct __old_sigaction {
+ __sighandler_t sa_handler;
+ __old_sigset_t sa_mask;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void); /* not used by Linux/SPARC yet */
+};
+
+typedef struct sigaltstack {
+ void __user *ss_sp;
+ int ss_flags;
+ size_t ss_size;
+} stack_t;
+
+#ifdef __KERNEL__
+
+struct k_sigaction {
+ struct __new_sigaction sa;
+ void __user *ka_restorer;
+};
+
+#define ptrace_signal_deliver(regs, cookie) do { } while (0)
+
+#endif /* !(__KERNEL__) */
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__SPARC_SIGNAL_H) */
diff --git a/arch/sparc/include/asm/signal_32.h b/arch/sparc/include/asm/signal_32.h
deleted file mode 100644
index 96a60ab03ca..00000000000
--- a/arch/sparc/include/asm/signal_32.h
+++ /dev/null
@@ -1,207 +0,0 @@
-#ifndef _ASMSPARC_SIGNAL_H
-#define _ASMSPARC_SIGNAL_H
-
-#include <asm/sigcontext.h>
-#include <linux/compiler.h>
-
-#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
-#include <linux/personality.h>
-#include <linux/types.h>
-#endif
-#endif
-
-/* On the Sparc the signal handlers get passed a 'sub-signal' code
- * for certain signal types, which we document here.
- */
-#define SIGHUP 1
-#define SIGINT 2
-#define SIGQUIT 3
-#define SIGILL 4
-#define SUBSIG_STACK 0
-#define SUBSIG_ILLINST 2
-#define SUBSIG_PRIVINST 3
-#define SUBSIG_BADTRAP(t) (0x80 + (t))
-
-#define SIGTRAP 5
-#define SIGABRT 6
-#define SIGIOT 6
-
-#define SIGEMT 7
-#define SUBSIG_TAG 10
-
-#define SIGFPE 8
-#define SUBSIG_FPDISABLED 0x400
-#define SUBSIG_FPERROR 0x404
-#define SUBSIG_FPINTOVFL 0x001
-#define SUBSIG_FPSTSIG 0x002
-#define SUBSIG_IDIVZERO 0x014
-#define SUBSIG_FPINEXACT 0x0c4
-#define SUBSIG_FPDIVZERO 0x0c8
-#define SUBSIG_FPUNFLOW 0x0cc
-#define SUBSIG_FPOPERROR 0x0d0
-#define SUBSIG_FPOVFLOW 0x0d4
-
-#define SIGKILL 9
-#define SIGBUS 10
-#define SUBSIG_BUSTIMEOUT 1
-#define SUBSIG_ALIGNMENT 2
-#define SUBSIG_MISCERROR 5
-
-#define SIGSEGV 11
-#define SUBSIG_NOMAPPING 3
-#define SUBSIG_PROTECTION 4
-#define SUBSIG_SEGERROR 5
-
-#define SIGSYS 12
-
-#define SIGPIPE 13
-#define SIGALRM 14
-#define SIGTERM 15
-#define SIGURG 16
-
-/* SunOS values which deviate from the Linux/i386 ones */
-#define SIGSTOP 17
-#define SIGTSTP 18
-#define SIGCONT 19
-#define SIGCHLD 20
-#define SIGTTIN 21
-#define SIGTTOU 22
-#define SIGIO 23
-#define SIGPOLL SIGIO /* SysV name for SIGIO */
-#define SIGXCPU 24
-#define SIGXFSZ 25
-#define SIGVTALRM 26
-#define SIGPROF 27
-#define SIGWINCH 28
-#define SIGLOST 29
-#define SIGPWR SIGLOST
-#define SIGUSR1 30
-#define SIGUSR2 31
-
-/* Most things should be clean enough to redefine this at will, if care
- * is taken to make libc match.
- */
-
-#define __OLD_NSIG 32
-#define __NEW_NSIG 64
-#define _NSIG_BPW 32
-#define _NSIG_WORDS (__NEW_NSIG / _NSIG_BPW)
-
-#define SIGRTMIN 32
-#define SIGRTMAX __NEW_NSIG
-
-#if defined(__KERNEL__) || defined(__WANT_POSIX1B_SIGNALS__)
-#define _NSIG __NEW_NSIG
-#define __new_sigset_t sigset_t
-#define __new_sigaction sigaction
-#define __old_sigset_t old_sigset_t
-#define __old_sigaction old_sigaction
-#else
-#define _NSIG __OLD_NSIG
-#define __old_sigset_t sigset_t
-#define __old_sigaction sigaction
-#endif
-
-#ifndef __ASSEMBLY__
-
-typedef unsigned long __old_sigset_t;
-
-typedef struct {
- unsigned long sig[_NSIG_WORDS];
-} __new_sigset_t;
-
-
-#ifdef __KERNEL__
-/* A SunOS sigstack */
-struct sigstack {
- char *the_stack;
- int cur_status;
-};
-#endif
-
-/* Sigvec flags */
-#define _SV_SSTACK 1u /* This signal handler should use sig-stack */
-#define _SV_INTR 2u /* Sig return should not restart system call */
-#define _SV_RESET 4u /* Set handler to SIG_DFL upon taken signal */
-#define _SV_IGNCHILD 8u /* Do not send SIGCHLD */
-
-/*
- * sa_flags values: SA_STACK is not currently supported, but will allow the
- * usage of signal stacks by using the (now obsolete) sa_restorer field in
- * the sigaction structure as a stack pointer. This is now possible due to
- * the changes in signal handling. LBT 010493.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- */
-#define SA_NOCLDSTOP _SV_IGNCHILD
-#define SA_STACK _SV_SSTACK
-#define SA_ONSTACK _SV_SSTACK
-#define SA_RESTART _SV_INTR
-#define SA_ONESHOT _SV_RESET
-#define SA_NOMASK 0x20u
-#define SA_NOCLDWAIT 0x100u
-#define SA_SIGINFO 0x200u
-
-#define SIG_BLOCK 0x01 /* for blocking signals */
-#define SIG_UNBLOCK 0x02 /* for unblocking signals */
-#define SIG_SETMASK 0x04 /* for setting the signal mask */
-
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK 1
-#define SS_DISABLE 2
-
-#define MINSIGSTKSZ 4096
-#define SIGSTKSZ 16384
-
-#ifdef __KERNEL__
-/*
- * DJHR
- * SA_STATIC_ALLOC is used for the SPARC system to indicate that this
- * interrupt handler's irq structure should be statically allocated
- * by the request_irq routine.
- * The alternative is that arch/sparc/kernel/irq.c has carnal knowledge
- * of interrupt usage and that sucks. Also without a flag like this
- * it may be possible for the free_irq routine to attempt to free
- * statically allocated data.. which is NOT GOOD.
- *
- */
-#define SA_STATIC_ALLOC 0x8000
-#endif
-
-#include <asm-generic/signal.h>
-
-#ifdef __KERNEL__
-struct __new_sigaction {
- __sighandler_t sa_handler;
- unsigned long sa_flags;
- void (*sa_restorer)(void); /* Not used by Linux/SPARC */
- __new_sigset_t sa_mask;
-};
-
-struct k_sigaction {
- struct __new_sigaction sa;
- void __user *ka_restorer;
-};
-
-struct __old_sigaction {
- __sighandler_t sa_handler;
- __old_sigset_t sa_mask;
- unsigned long sa_flags;
- void (*sa_restorer) (void); /* not used by Linux/SPARC */
-};
-
-typedef struct sigaltstack {
- void __user *ss_sp;
- int ss_flags;
- size_t ss_size;
-} stack_t;
-
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
-#endif /* !(__KERNEL__) */
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(_ASMSPARC_SIGNAL_H) */
diff --git a/arch/sparc/include/asm/signal_64.h b/arch/sparc/include/asm/signal_64.h
deleted file mode 100644
index ab1509a101c..00000000000
--- a/arch/sparc/include/asm/signal_64.h
+++ /dev/null
@@ -1,194 +0,0 @@
-#ifndef _ASMSPARC64_SIGNAL_H
-#define _ASMSPARC64_SIGNAL_H
-
-#include <asm/sigcontext.h>
-
-#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
-#include <linux/personality.h>
-#include <linux/types.h>
-#endif
-#endif
-
-/* On the Sparc the signal handlers get passed a 'sub-signal' code
- * for certain signal types, which we document here.
- */
-#define SIGHUP 1
-#define SIGINT 2
-#define SIGQUIT 3
-#define SIGILL 4
-#define SUBSIG_STACK 0
-#define SUBSIG_ILLINST 2
-#define SUBSIG_PRIVINST 3
-#define SUBSIG_BADTRAP(t) (0x80 + (t))
-
-#define SIGTRAP 5
-#define SIGABRT 6
-#define SIGIOT 6
-
-#define SIGEMT 7
-#define SUBSIG_TAG 10
-
-#define SIGFPE 8
-#define SUBSIG_FPDISABLED 0x400
-#define SUBSIG_FPERROR 0x404
-#define SUBSIG_FPINTOVFL 0x001
-#define SUBSIG_FPSTSIG 0x002
-#define SUBSIG_IDIVZERO 0x014
-#define SUBSIG_FPINEXACT 0x0c4
-#define SUBSIG_FPDIVZERO 0x0c8
-#define SUBSIG_FPUNFLOW 0x0cc
-#define SUBSIG_FPOPERROR 0x0d0
-#define SUBSIG_FPOVFLOW 0x0d4
-
-#define SIGKILL 9
-#define SIGBUS 10
-#define SUBSIG_BUSTIMEOUT 1
-#define SUBSIG_ALIGNMENT 2
-#define SUBSIG_MISCERROR 5
-
-#define SIGSEGV 11
-#define SUBSIG_NOMAPPING 3
-#define SUBSIG_PROTECTION 4
-#define SUBSIG_SEGERROR 5
-
-#define SIGSYS 12
-
-#define SIGPIPE 13
-#define SIGALRM 14
-#define SIGTERM 15
-#define SIGURG 16
-
-/* SunOS values which deviate from the Linux/i386 ones */
-#define SIGSTOP 17
-#define SIGTSTP 18
-#define SIGCONT 19
-#define SIGCHLD 20
-#define SIGTTIN 21
-#define SIGTTOU 22
-#define SIGIO 23
-#define SIGPOLL SIGIO /* SysV name for SIGIO */
-#define SIGXCPU 24
-#define SIGXFSZ 25
-#define SIGVTALRM 26
-#define SIGPROF 27
-#define SIGWINCH 28
-#define SIGLOST 29
-#define SIGPWR SIGLOST
-#define SIGUSR1 30
-#define SIGUSR2 31
-
-/* Most things should be clean enough to redefine this at will, if care
- is taken to make libc match. */
-
-#define __OLD_NSIG 32
-#define __NEW_NSIG 64
-#define _NSIG_BPW 64
-#define _NSIG_WORDS (__NEW_NSIG / _NSIG_BPW)
-
-#define SIGRTMIN 32
-#define SIGRTMAX __NEW_NSIG
-
-#if defined(__KERNEL__) || defined(__WANT_POSIX1B_SIGNALS__)
-#define _NSIG __NEW_NSIG
-#define __new_sigset_t sigset_t
-#define __new_sigaction sigaction
-#define __new_sigaction32 sigaction32
-#define __old_sigset_t old_sigset_t
-#define __old_sigaction old_sigaction
-#define __old_sigaction32 old_sigaction32
-#else
-#define _NSIG __OLD_NSIG
-#define NSIG _NSIG
-#define __old_sigset_t sigset_t
-#define __old_sigaction sigaction
-#define __old_sigaction32 sigaction32
-#endif
-
-#ifndef __ASSEMBLY__
-
-typedef unsigned long __old_sigset_t; /* at least 32 bits */
-
-typedef struct {
- unsigned long sig[_NSIG_WORDS];
-} __new_sigset_t;
-
-/* A SunOS sigstack */
-struct sigstack {
- /* XXX 32-bit pointers pinhead XXX */
- char *the_stack;
- int cur_status;
-};
-
-/* Sigvec flags */
-#define _SV_SSTACK 1u /* This signal handler should use sig-stack */
-#define _SV_INTR 2u /* Sig return should not restart system call */
-#define _SV_RESET 4u /* Set handler to SIG_DFL upon taken signal */
-#define _SV_IGNCHILD 8u /* Do not send SIGCHLD */
-
-/*
- * sa_flags values: SA_STACK is not currently supported, but will allow the
- * usage of signal stacks by using the (now obsolete) sa_restorer field in
- * the sigaction structure as a stack pointer. This is now possible due to
- * the changes in signal handling. LBT 010493.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- */
-#define SA_NOCLDSTOP _SV_IGNCHILD
-#define SA_STACK _SV_SSTACK
-#define SA_ONSTACK _SV_SSTACK
-#define SA_RESTART _SV_INTR
-#define SA_ONESHOT _SV_RESET
-#define SA_NOMASK 0x20u
-#define SA_NOCLDWAIT 0x100u
-#define SA_SIGINFO 0x200u
-
-
-#define SIG_BLOCK 0x01 /* for blocking signals */
-#define SIG_UNBLOCK 0x02 /* for unblocking signals */
-#define SIG_SETMASK 0x04 /* for setting the signal mask */
-
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK 1
-#define SS_DISABLE 2
-
-#define MINSIGSTKSZ 4096
-#define SIGSTKSZ 16384
-
-#include <asm-generic/signal.h>
-
-struct __new_sigaction {
- __sighandler_t sa_handler;
- unsigned long sa_flags;
- __sigrestore_t sa_restorer; /* not used by Linux/SPARC yet */
- __new_sigset_t sa_mask;
-};
-
-struct __old_sigaction {
- __sighandler_t sa_handler;
- __old_sigset_t sa_mask;
- unsigned long sa_flags;
- void (*sa_restorer)(void); /* not used by Linux/SPARC yet */
-};
-
-typedef struct sigaltstack {
- void __user *ss_sp;
- int ss_flags;
- size_t ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
-
-struct k_sigaction {
- struct __new_sigaction sa;
- void __user *ka_restorer;
-};
-
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
-#endif /* !(__KERNEL__) */
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(_ASMSPARC64_SIGNAL_H) */
diff --git a/arch/sparc/include/asm/smp_32.h b/arch/sparc/include/asm/smp_32.h
index 8408d9d2a66..58101dc7049 100644
--- a/arch/sparc/include/asm/smp_32.h
+++ b/arch/sparc/include/asm/smp_32.h
@@ -170,7 +170,4 @@ void smp_setup_cpu_possible_map(void);
#define smp_setup_cpu_possible_map() do { } while (0)
#endif /* !(SMP) */
-
-#define NO_PROC_ID 0xFF
-
#endif /* !(_SPARC_SMP_H) */
diff --git a/arch/sparc/include/asm/stat.h b/arch/sparc/include/asm/stat.h
index d8153013df7..55db5eca08e 100644
--- a/arch/sparc/include/asm/stat.h
+++ b/arch/sparc/include/asm/stat.h
@@ -1,8 +1,107 @@
-#ifndef ___ASM_SPARC_STAT_H
-#define ___ASM_SPARC_STAT_H
+#ifndef __SPARC_STAT_H
+#define __SPARC_STAT_H
+
+#include <linux/types.h>
+
#if defined(__sparc__) && defined(__arch64__)
-#include <asm/stat_64.h>
+/* 64 bit sparc */
+struct stat {
+ unsigned st_dev;
+ ino_t st_ino;
+ mode_t st_mode;
+ short st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ unsigned st_rdev;
+ off_t st_size;
+ time_t st_atime;
+ time_t st_mtime;
+ time_t st_ctime;
+ off_t st_blksize;
+ off_t st_blocks;
+ unsigned long __unused4[2];
+};
+
+struct stat64 {
+ unsigned long st_dev;
+ unsigned long st_ino;
+ unsigned long st_nlink;
+
+ unsigned int st_mode;
+ unsigned int st_uid;
+ unsigned int st_gid;
+ unsigned int __pad0;
+
+ unsigned long st_rdev;
+ long st_size;
+ long st_blksize;
+ long st_blocks;
+
+ unsigned long st_atime;
+ unsigned long st_atime_nsec;
+ unsigned long st_mtime;
+ unsigned long st_mtime_nsec;
+ unsigned long st_ctime;
+ unsigned long st_ctime_nsec;
+ long __unused[3];
+};
+
#else
-#include <asm/stat_32.h>
-#endif
-#endif
+/* 32 bit sparc */
+struct stat {
+ unsigned short st_dev;
+ ino_t st_ino;
+ mode_t st_mode;
+ short st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ unsigned short st_rdev;
+ off_t st_size;
+ time_t st_atime;
+ unsigned long st_atime_nsec;
+ time_t st_mtime;
+ unsigned long st_mtime_nsec;
+ time_t st_ctime;
+ unsigned long st_ctime_nsec;
+ off_t st_blksize;
+ off_t st_blocks;
+ unsigned long __unused4[2];
+};
+
+#define STAT_HAVE_NSEC 1
+
+struct stat64 {
+ unsigned long long st_dev;
+
+ unsigned long long st_ino;
+
+ unsigned int st_mode;
+ unsigned int st_nlink;
+
+ unsigned int st_uid;
+ unsigned int st_gid;
+
+ unsigned long long st_rdev;
+
+ unsigned char __pad3[8];
+
+ long long st_size;
+ unsigned int st_blksize;
+
+ unsigned char __pad4[8];
+ unsigned int st_blocks;
+
+ unsigned int st_atime;
+ unsigned int st_atime_nsec;
+
+ unsigned int st_mtime;
+ unsigned int st_mtime_nsec;
+
+ unsigned int st_ctime;
+ unsigned int st_ctime_nsec;
+
+ unsigned int __unused4;
+ unsigned int __unused5;
+};
+#endif /* defined(__sparc__) && defined(__arch64__) */
+#endif /* __SPARC_STAT_H */
diff --git a/arch/sparc/include/asm/stat_32.h b/arch/sparc/include/asm/stat_32.h
deleted file mode 100644
index 2299e1d5d94..00000000000
--- a/arch/sparc/include/asm/stat_32.h
+++ /dev/null
@@ -1,76 +0,0 @@
-#ifndef _SPARC_STAT_H
-#define _SPARC_STAT_H
-
-#include <linux/types.h>
-
-struct __old_kernel_stat {
- unsigned short st_dev;
- unsigned short st_ino;
- unsigned short st_mode;
- unsigned short st_nlink;
- unsigned short st_uid;
- unsigned short st_gid;
- unsigned short st_rdev;
- unsigned long st_size;
- unsigned long st_atime;
- unsigned long st_mtime;
- unsigned long st_ctime;
-};
-
-struct stat {
- unsigned short st_dev;
- unsigned long st_ino;
- unsigned short st_mode;
- short st_nlink;
- unsigned short st_uid;
- unsigned short st_gid;
- unsigned short st_rdev;
- long st_size;
- long st_atime;
- unsigned long st_atime_nsec;
- long st_mtime;
- unsigned long st_mtime_nsec;
- long st_ctime;
- unsigned long st_ctime_nsec;
- long st_blksize;
- long st_blocks;
- unsigned long __unused4[2];
-};
-
-#define STAT_HAVE_NSEC 1
-
-struct stat64 {
- unsigned long long st_dev;
-
- unsigned long long st_ino;
-
- unsigned int st_mode;
- unsigned int st_nlink;
-
- unsigned int st_uid;
- unsigned int st_gid;
-
- unsigned long long st_rdev;
-
- unsigned char __pad3[8];
-
- long long st_size;
- unsigned int st_blksize;
-
- unsigned char __pad4[8];
- unsigned int st_blocks;
-
- unsigned int st_atime;
- unsigned int st_atime_nsec;
-
- unsigned int st_mtime;
- unsigned int st_mtime_nsec;
-
- unsigned int st_ctime;
- unsigned int st_ctime_nsec;
-
- unsigned int __unused4;
- unsigned int __unused5;
-};
-
-#endif
diff --git a/arch/sparc/include/asm/stat_64.h b/arch/sparc/include/asm/stat_64.h
deleted file mode 100644
index 9650fdea847..00000000000
--- a/arch/sparc/include/asm/stat_64.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef _SPARC64_STAT_H
-#define _SPARC64_STAT_H
-
-#include <linux/types.h>
-
-struct stat {
- unsigned st_dev;
- ino_t st_ino;
- mode_t st_mode;
- short st_nlink;
- uid_t st_uid;
- gid_t st_gid;
- unsigned st_rdev;
- off_t st_size;
- time_t st_atime;
- time_t st_mtime;
- time_t st_ctime;
- off_t st_blksize;
- off_t st_blocks;
- unsigned long __unused4[2];
-};
-
-struct stat64 {
- unsigned long st_dev;
- unsigned long st_ino;
- unsigned long st_nlink;
-
- unsigned int st_mode;
- unsigned int st_uid;
- unsigned int st_gid;
- unsigned int __pad0;
-
- unsigned long st_rdev;
- long st_size;
- long st_blksize;
- long st_blocks;
-
- unsigned long st_atime;
- unsigned long st_atime_nsec;
- unsigned long st_mtime;
- unsigned long st_mtime_nsec;
- unsigned long st_ctime;
- unsigned long st_ctime_nsec;
- long __unused[3];
-};
-
-#endif
diff --git a/arch/sparc/include/asm/thread_info_32.h b/arch/sparc/include/asm/thread_info_32.h
index 80fe547c3f4..0f7b0e5fb1c 100644
--- a/arch/sparc/include/asm/thread_info_32.h
+++ b/arch/sparc/include/asm/thread_info_32.h
@@ -45,7 +45,7 @@ struct thread_info {
/* A place to store user windows and stack pointers
* when the stack needs inspection.
*/
- struct reg_window reg_window[NSWINS]; /* align for ldd! */
+ struct reg_window32 reg_window[NSWINS]; /* align for ldd! */
unsigned long rwbuf_stkptrs[NSWINS];
unsigned long w_saved;
diff --git a/arch/sparc/include/asm/traps.h b/arch/sparc/include/asm/traps.h
index bebdbf8f43a..3aa62dde343 100644
--- a/arch/sparc/include/asm/traps.h
+++ b/arch/sparc/include/asm/traps.h
@@ -10,7 +10,7 @@
#define NUM_SPARC_TRAPS 255
#ifndef __ASSEMBLY__
-
+#ifdef __KERNEL__
/* This is for V8 compliant Sparc CPUS */
struct tt_entry {
unsigned long inst_one;
@@ -22,14 +22,7 @@ struct tt_entry {
/* We set this to _start in system setup. */
extern struct tt_entry *sparc_ttable;
-static inline unsigned long get_tbr(void)
-{
- unsigned long tbr;
-
- __asm__ __volatile__("rd %%tbr, %0\n\t" : "=r" (tbr));
- return tbr;
-}
-
+#endif /* (__KERNEL__) */
#endif /* !(__ASSEMBLY__) */
/* For patching the trap table at boot time, we need to know how to
diff --git a/arch/sparc/kernel/irq_32.c b/arch/sparc/kernel/irq_32.c
index f3488c45d57..1eff942fe22 100644
--- a/arch/sparc/kernel/irq_32.c
+++ b/arch/sparc/kernel/irq_32.c
@@ -669,7 +669,9 @@ void __init init_IRQ(void)
btfixup();
}
+#ifdef CONFIG_PROC_FS
void init_irq_proc(void)
{
/* For now, nothing... */
}
+#endif /* CONFIG_PROC_FS */
diff --git a/arch/sparc/kernel/kgdb_32.c b/arch/sparc/kernel/kgdb_32.c
index 757805ce02e..04df4edc007 100644
--- a/arch/sparc/kernel/kgdb_32.c
+++ b/arch/sparc/kernel/kgdb_32.c
@@ -14,14 +14,14 @@ extern unsigned long trapbase;
void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
{
- struct reg_window *win;
+ struct reg_window32 *win;
int i;
gdb_regs[GDB_G0] = 0;
for (i = 0; i < 15; i++)
gdb_regs[GDB_G1 + i] = regs->u_regs[UREG_G1 + i];
- win = (struct reg_window *) regs->u_regs[UREG_FP];
+ win = (struct reg_window32 *) regs->u_regs[UREG_FP];
for (i = 0; i < 8; i++)
gdb_regs[GDB_L0 + i] = win->locals[i];
for (i = 0; i < 8; i++)
@@ -43,7 +43,7 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
{
struct thread_info *t = task_thread_info(p);
- struct reg_window *win;
+ struct reg_window32 *win;
int i;
for (i = GDB_G0; i < GDB_G6; i++)
@@ -55,7 +55,7 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
gdb_regs[GDB_SP] = t->ksp;
gdb_regs[GDB_O7] = 0;
- win = (struct reg_window *) t->ksp;
+ win = (struct reg_window32 *) t->ksp;
for (i = 0; i < 8; i++)
gdb_regs[GDB_L0 + i] = win->locals[i];
for (i = 0; i < 8; i++)
@@ -77,7 +77,7 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
{
- struct reg_window *win;
+ struct reg_window32 *win;
int i;
for (i = 0; i < 15; i++)
@@ -96,7 +96,7 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
regs->npc = gdb_regs[GDB_NPC];
regs->y = gdb_regs[GDB_Y];
- win = (struct reg_window *) regs->u_regs[UREG_FP];
+ win = (struct reg_window32 *) regs->u_regs[UREG_FP];
for (i = 0; i < 8; i++)
win->locals[i] = gdb_regs[GDB_L0 + i];
for (i = 0; i < 8; i++)
diff --git a/arch/sparc/kernel/muldiv.c b/arch/sparc/kernel/muldiv.c
index ba960c02bb5..6ce1021d487 100644
--- a/arch/sparc/kernel/muldiv.c
+++ b/arch/sparc/kernel/muldiv.c
@@ -60,7 +60,7 @@ static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
}
#define fetch_reg(reg, regs) ({ \
- struct reg_window __user *win; \
+ struct reg_window32 __user *win; \
register unsigned long ret; \
\
if (!(reg)) ret = 0; \
@@ -68,7 +68,7 @@ static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
ret = regs->u_regs[(reg)]; \
} else { \
/* Ho hum, the slightly complicated case. */ \
- win = (struct reg_window __user *)regs->u_regs[UREG_FP];\
+ win = (struct reg_window32 __user *)regs->u_regs[UREG_FP];\
if (get_user (ret, &win->locals[(reg) - 16])) return -1;\
} \
ret; \
@@ -77,7 +77,7 @@ static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
static inline int
store_reg(unsigned int result, unsigned int reg, struct pt_regs *regs)
{
- struct reg_window __user *win;
+ struct reg_window32 __user *win;
if (!reg)
return 0;
@@ -86,7 +86,7 @@ store_reg(unsigned int result, unsigned int reg, struct pt_regs *regs)
return 0;
} else {
/* need to use put_user() in this case: */
- win = (struct reg_window __user *) regs->u_regs[UREG_FP];
+ win = (struct reg_window32 __user *) regs->u_regs[UREG_FP];
return (put_user(result, &win->locals[reg - 16]));
}
}
diff --git a/arch/sparc/kernel/pci_psycho.c b/arch/sparc/kernel/pci_psycho.c
index dfb3ec89298..3b34344082e 100644
--- a/arch/sparc/kernel/pci_psycho.c
+++ b/arch/sparc/kernel/pci_psycho.c
@@ -307,10 +307,7 @@ static void psycho_register_error_handlers(struct pci_pbm_info *pbm)
/* We really mean to ignore the return result here. Two
* PCI controller share the same interrupt numbers and
- * drive the same front-end hardware. Whichever of the
- * two get in here first will register the IRQ handler
- * the second will just error out since we do not pass in
- * IRQF_SHARED.
+ * drive the same front-end hardware.
*/
err = request_irq(op->irqs[1], psycho_ue_intr, IRQF_SHARED,
"PSYCHO_UE", pbm);
diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c
index 69d9315f4a9..5a8d8ced33d 100644
--- a/arch/sparc/kernel/process_32.c
+++ b/arch/sparc/kernel/process_32.c
@@ -180,13 +180,13 @@ static DEFINE_SPINLOCK(sparc_backtrace_lock);
void __show_backtrace(unsigned long fp)
{
- struct reg_window *rw;
+ struct reg_window32 *rw;
unsigned long flags;
int cpu = smp_processor_id();
spin_lock_irqsave(&sparc_backtrace_lock, flags);
- rw = (struct reg_window *)fp;
+ rw = (struct reg_window32 *)fp;
while(rw && (((unsigned long) rw) >= PAGE_OFFSET) &&
!(((unsigned long) rw) & 0x7)) {
printk("CPU[%d]: ARGS[%08lx,%08lx,%08lx,%08lx,%08lx,%08lx] "
@@ -196,7 +196,7 @@ void __show_backtrace(unsigned long fp)
rw->ins[6],
rw->ins[7]);
printk("%pS\n", (void *) rw->ins[7]);
- rw = (struct reg_window *) rw->ins[6];
+ rw = (struct reg_window32 *) rw->ins[6];
}
spin_unlock_irqrestore(&sparc_backtrace_lock, flags);
}
@@ -258,7 +258,7 @@ void show_stackframe(struct sparc_stackf *sf)
void show_regs(struct pt_regs *r)
{
- struct reg_window *rw = (struct reg_window *) r->u_regs[14];
+ struct reg_window32 *rw = (struct reg_window32 *) r->u_regs[14];
printk("PSR: %08lx PC: %08lx NPC: %08lx Y: %08lx %s\n",
r->psr, r->pc, r->npc, r->y, print_tainted());
@@ -287,7 +287,7 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp)
{
unsigned long pc, fp;
unsigned long task_base;
- struct reg_window *rw;
+ struct reg_window32 *rw;
int count = 0;
if (tsk != NULL)
@@ -301,7 +301,7 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp)
if (fp < (task_base + sizeof(struct thread_info)) ||
fp >= (task_base + (PAGE_SIZE << 1)))
break;
- rw = (struct reg_window *) fp;
+ rw = (struct reg_window32 *) fp;
pc = rw->ins[7];
printk("[%08lx : ", pc);
printk("%pS ] ", (void *) pc);
@@ -679,7 +679,7 @@ unsigned long get_wchan(struct task_struct *task)
unsigned long pc, fp, bias = 0;
unsigned long task_base = (unsigned long) task;
unsigned long ret = 0;
- struct reg_window *rw;
+ struct reg_window32 *rw;
int count = 0;
if (!task || task == current ||
@@ -692,7 +692,7 @@ unsigned long get_wchan(struct task_struct *task)
if (fp < (task_base + sizeof(struct thread_info)) ||
fp >= (task_base + (2 * PAGE_SIZE)))
break;
- rw = (struct reg_window *) fp;
+ rw = (struct reg_window32 *) fp;
pc = rw->ins[7];
if (!in_sched_functions(pc)) {
ret = pc;
diff --git a/arch/sparc/kernel/prom_common.c b/arch/sparc/kernel/prom_common.c
index 4e9af593db4..ff7b591c894 100644
--- a/arch/sparc/kernel/prom_common.c
+++ b/arch/sparc/kernel/prom_common.c
@@ -155,20 +155,12 @@ static struct property * __init build_one_prop(phandle node, char *prev,
p->value = prom_early_alloc(special_len);
memcpy(p->value, special_val, special_len);
} else {
-#ifdef CONFIG_SPARC32
- if (prev == NULL) {
- name = prom_firstprop(node, NULL);
- } else {
- name = prom_nextprop(node, prev, NULL);
- }
-#else
if (prev == NULL) {
- prom_firstprop(node, p->name);
+ name = prom_firstprop(node, p->name);
} else {
- prom_nextprop(node, prev, p->name);
+ name = prom_nextprop(node, prev, p->name);
}
- name = p->name;
-#endif
+
if (strlen(name) == 0) {
tmp = p;
return NULL;
diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c
index c94f91c8b6e..181d069a2d4 100644
--- a/arch/sparc/kernel/signal_32.c
+++ b/arch/sparc/kernel/signal_32.c
@@ -34,7 +34,7 @@ extern void fpload(unsigned long *fpregs, unsigned long *fsr);
struct signal_frame {
struct sparc_stackf ss;
- __siginfo_t info;
+ __siginfo32_t info;
__siginfo_fpu_t __user *fpu_save;
unsigned long insns[2] __attribute__ ((aligned (8)));
unsigned int extramask[_NSIG_WORDS - 1];
@@ -351,7 +351,7 @@ static void setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
err |= __copy_to_user(sf->extramask, &oldset->sig[1],
(_NSIG_WORDS - 1) * sizeof(unsigned int));
err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP],
- sizeof(struct reg_window));
+ sizeof(struct reg_window32));
if (err)
goto sigsegv;
@@ -433,7 +433,7 @@ static void setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
err |= __put_user(current->sas_ss_size, &sf->stack.ss_size);
err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP],
- sizeof(struct reg_window));
+ sizeof(struct reg_window32));
err |= copy_siginfo_to_user(&sf->info, info);
diff --git a/arch/sparc/kernel/traps_32.c b/arch/sparc/kernel/traps_32.c
index 716f3946c49..213645be6e9 100644
--- a/arch/sparc/kernel/traps_32.c
+++ b/arch/sparc/kernel/traps_32.c
@@ -67,7 +67,7 @@ void die_if_kernel(char *str, struct pt_regs *regs)
__RESTORE; __RESTORE; __RESTORE; __RESTORE;
{
- struct reg_window *rw = (struct reg_window *)regs->u_regs[UREG_FP];
+ struct reg_window32 *rw = (struct reg_window32 *)regs->u_regs[UREG_FP];
/* Stop the back trace when we hit userland or we
* find some badly aligned kernel stack. Set an upper
@@ -79,7 +79,7 @@ void die_if_kernel(char *str, struct pt_regs *regs)
!(((unsigned long) rw) & 0x7)) {
printk("Caller[%08lx]: %pS\n", rw->ins[7],
(void *) rw->ins[7]);
- rw = (struct reg_window *)rw->ins[6];
+ rw = (struct reg_window32 *)rw->ins[6];
}
}
printk("Instruction DUMP:");
diff --git a/arch/sparc/kernel/unaligned_32.c b/arch/sparc/kernel/unaligned_32.c
index c2a28c5ad65..6b1e6cde6ff 100644
--- a/arch/sparc/kernel/unaligned_32.c
+++ b/arch/sparc/kernel/unaligned_32.c
@@ -97,26 +97,26 @@ static inline int sign_extend_imm13(int imm)
static inline unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
{
- struct reg_window *win;
+ struct reg_window32 *win;
if(reg < 16)
return (!reg ? 0 : regs->u_regs[reg]);
/* Ho hum, the slightly complicated case. */
- win = (struct reg_window *) regs->u_regs[UREG_FP];
+ win = (struct reg_window32 *) regs->u_regs[UREG_FP];
return win->locals[reg - 16]; /* yes, I know what this does... */
}
static inline unsigned long safe_fetch_reg(unsigned int reg, struct pt_regs *regs)
{
- struct reg_window __user *win;
+ struct reg_window32 __user *win;
unsigned long ret;
if (reg < 16)
return (!reg ? 0 : regs->u_regs[reg]);
/* Ho hum, the slightly complicated case. */
- win = (struct reg_window __user *) regs->u_regs[UREG_FP];
+ win = (struct reg_window32 __user *) regs->u_regs[UREG_FP];
if ((unsigned long)win & 3)
return -1;
@@ -129,11 +129,11 @@ static inline unsigned long safe_fetch_reg(unsigned int reg, struct pt_regs *reg
static inline unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs)
{
- struct reg_window *win;
+ struct reg_window32 *win;
if(reg < 16)
return &regs->u_regs[reg];
- win = (struct reg_window *) regs->u_regs[UREG_FP];
+ win = (struct reg_window32 *) regs->u_regs[UREG_FP];
return &win->locals[reg - 16];
}
diff --git a/arch/sparc/kernel/windows.c b/arch/sparc/kernel/windows.c
index 9cc93eaa4ab..f24d298bda2 100644
--- a/arch/sparc/kernel/windows.c
+++ b/arch/sparc/kernel/windows.c
@@ -42,7 +42,7 @@ static inline void shift_window_buffer(int first_win, int last_win, struct threa
for(i = first_win; i < last_win; i++) {
tp->rwbuf_stkptrs[i] = tp->rwbuf_stkptrs[i+1];
- memcpy(&tp->reg_window[i], &tp->reg_window[i+1], sizeof(struct reg_window));
+ memcpy(&tp->reg_window[i], &tp->reg_window[i+1], sizeof(struct reg_window32));
}
}
@@ -70,7 +70,7 @@ void synchronize_user_stack(void)
/* Ok, let it rip. */
if (copy_to_user((char __user *) sp, &tp->reg_window[window],
- sizeof(struct reg_window)))
+ sizeof(struct reg_window32)))
continue;
shift_window_buffer(window, tp->w_saved - 1, tp);
@@ -119,7 +119,7 @@ void try_to_clear_window_buffer(struct pt_regs *regs, int who)
if ((sp & 7) ||
copy_to_user((char __user *) sp, &tp->reg_window[window],
- sizeof(struct reg_window)))
+ sizeof(struct reg_window32)))
do_exit(SIGILL);
}
tp->w_saved = 0;
diff --git a/arch/um/Makefile b/arch/um/Makefile
index d944c343acd..0728def3223 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -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
diff --git a/arch/um/include/asm/system.h b/arch/um/include/asm/system.h
index ae5f94d6317..753346e2cdf 100644
--- a/arch/um/include/asm/system.h
+++ b/arch/um/include/asm/system.h
@@ -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); \
})
diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
index 85a78575956..8078955845a 100644
--- a/arch/x86/Kconfig.cpu
+++ b/arch/x86/Kconfig.cpu
@@ -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
diff --git a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
index b8e05ee4f73..beea4466b06 100644
--- a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
+++ b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
@@ -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,
};
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
index 3b5f06423e7..f0ea6fa2f53 100644
--- a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -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);
}
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c b/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c
index 98d4fdb7dc0..cdac7d62369 100644
--- a/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c
+++ b/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c
@@ -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");
}
diff --git a/arch/x86/kernel/pci-swiotlb_64.c b/arch/x86/kernel/pci-swiotlb_64.c
index 242c3440687..8cba3749a51 100644
--- a/arch/x86/kernel/pci-swiotlb_64.c
+++ b/arch/x86/kernel/pci-swiotlb_64.c
@@ -13,7 +13,7 @@
int swiotlb __read_mostly;
-void *swiotlb_alloc_boot(size_t size, unsigned long nslabs)
+void * __init swiotlb_alloc_boot(size_t size, unsigned long nslabs)
{
return alloc_bootmem_low_pages(size);
}
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 31d6f535a79..01dde80597f 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -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;
}
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index b4fd8ca701a..e85c8fe9ffc 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -85,14 +85,14 @@ config HID_COMPAT
config HID_A4TECH
tristate "A4 tech" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for A4 tech X5 and WOP-35 / Trust 450L mice.
config HID_APPLE
tristate "Apple" if EMBEDDED
depends on (USB_HID || BT_HIDP)
- default y
+ default !EMBEDDED
---help---
Support for some Apple devices which less or more break
HID specification.
@@ -103,64 +103,49 @@ config HID_APPLE
config HID_BELKIN
tristate "Belkin" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Belkin Flip KVM and Wireless keyboard.
-config HID_BRIGHT
- tristate "Bright" if EMBEDDED
- depends on USB_HID
- default y
- ---help---
- Support for Bright ABNT-2 keyboard.
-
config HID_CHERRY
tristate "Cherry" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Cherry Cymotion keyboard.
config HID_CHICONY
tristate "Chicony" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Chicony Tactical pad.
config HID_CYPRESS
tristate "Cypress" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for cypress mouse and barcode readers.
-config HID_DELL
- tristate "Dell" if EMBEDDED
- depends on USB_HID
- default y
- ---help---
- Support for quirky Dell HID hardware that require
- special LED handling (W7658 and SK8115 models)
-
config HID_EZKEY
tristate "Ezkey" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Ezkey BTC 8193 keyboard.
config HID_GYRATION
tristate "Gyration" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Gyration remote control.
config HID_LOGITECH
tristate "Logitech" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Logitech devices that are not fully compliant with HID standard.
@@ -191,21 +176,28 @@ config LOGIRUMBLEPAD2_FF
config HID_MICROSOFT
tristate "Microsoft" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Microsoft devices that are not fully compliant with HID standard.
config HID_MONTEREY
tristate "Monterey" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Monterey Genius KB29E.
+config HID_NTRIG
+ tristate "NTrig" if EMBEDDED
+ depends on USB_HID
+ default !EMBEDDED
+ ---help---
+ Support for N-Trig touch screen.
+
config HID_PANTHERLORD
tristate "Pantherlord devices support" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for PantherLord/GreenAsia based device support.
@@ -220,31 +212,47 @@ config PANTHERLORD_FF
config HID_PETALYNX
tristate "Petalynx" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Petalynx Maxter remote control.
config HID_SAMSUNG
tristate "Samsung" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Samsung InfraRed remote control.
config HID_SONY
tristate "Sony" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Sony PS3 controller.
config HID_SUNPLUS
tristate "Sunplus" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Sunplus wireless desktop.
+config GREENASIA_FF
+ tristate "GreenAsia (Product ID 0x12) force feedback support"
+ depends on USB_HID
+ select INPUT_FF_MEMLESS
+ ---help---
+ Say Y here if you have a GreenAsia (Product ID 0x12) based game controller
+ (like MANTA Warior MM816 and SpeedLink Strike2 SL-6635) or adapter
+ and want to enable force feedback support for it.
+
+config HID_TOPSEED
+ tristate "TopSeed Cyberlink remote control support" if EMBEDDED
+ depends on USB_HID
+ default !EMBEDDED
+ ---help---
+ Say Y if you have a TopSeed Cyberlink remote control.
+
config THRUSTMASTER_FF
tristate "ThrustMaster devices support"
depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index b09e43e7413..fbd021f153f 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -23,22 +23,23 @@ endif
obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o
obj-$(CONFIG_HID_APPLE) += hid-apple.o
obj-$(CONFIG_HID_BELKIN) += hid-belkin.o
-obj-$(CONFIG_HID_BRIGHT) += hid-bright.o
obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
obj-$(CONFIG_HID_CHICONY) += hid-chicony.o
obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
-obj-$(CONFIG_HID_DELL) += hid-dell.o
obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o
obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o
obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o
+obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o
obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o
obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o
obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
obj-$(CONFIG_HID_SONY) += hid-sony.o
obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o
+obj-$(CONFIG_GREENASIA_FF) += hid-gaff.o
obj-$(CONFIG_THRUSTMASTER_FF) += hid-tmff.o
+obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o
obj-$(CONFIG_ZEROPLUS_FF) += hid-zpff.o
obj-$(CONFIG_USB_HID) += usbhid/
diff --git a/drivers/hid/hid-bright.c b/drivers/hid/hid-bright.c
deleted file mode 100644
index 38517a117df..00000000000
--- a/drivers/hid/hid-bright.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * HID driver for some bright "special" devices
- *
- * Copyright (c) 2008 Mauro Carvalho Chehab <mchehab@redhat.com>
- *
- * Based on hid-dell driver
- */
-
-/*
- * 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/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-
-#include "hid-ids.h"
-
-static int bright_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
- int ret;
-
- ret = hid_parse(hdev);
- if (ret) {
- dev_err(&hdev->dev, "parse failed\n");
- goto err_free;
- }
-
- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- if (ret) {
- dev_err(&hdev->dev, "hw start failed\n");
- goto err_free;
- }
-
- usbhid_set_leds(hdev);
-
- return 0;
-err_free:
- return ret;
-}
-
-static const struct hid_device_id bright_devices[] = {
- { HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) },
- { }
-};
-MODULE_DEVICE_TABLE(hid, bright_devices);
-
-static struct hid_driver bright_driver = {
- .name = "bright",
- .id_table = bright_devices,
- .probe = bright_probe,
-};
-
-static int bright_init(void)
-{
- return hid_register_driver(&bright_driver);
-}
-
-static void bright_exit(void)
-{
- hid_unregister_driver(&bright_driver);
-}
-
-module_init(bright_init);
-module_exit(bright_exit);
-MODULE_LICENSE("GPL");
-
-HID_COMPAT_LOAD_DRIVER(bright);
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 40df3e1b4bd..5d7640e49dc 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1256,19 +1256,16 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
- { HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
- { HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
@@ -1279,7 +1276,6 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) },
- { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) },
@@ -1297,23 +1293,105 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
{ }
};
+struct hid_dynid {
+ struct list_head list;
+ struct hid_device_id id;
+};
+
+/**
+ * store_new_id - add a new HID device ID to this driver and re-probe devices
+ * @driver: target device driver
+ * @buf: buffer for scanning device ID data
+ * @count: input size
+ *
+ * Adds a new dynamic hid device ID to this driver,
+ * and causes the driver to probe for all devices again.
+ */
+static ssize_t store_new_id(struct device_driver *drv, const char *buf,
+ size_t count)
+{
+ struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver);
+ struct hid_dynid *dynid;
+ __u32 bus, vendor, product;
+ unsigned long driver_data = 0;
+ int ret;
+
+ ret = sscanf(buf, "%x %x %x %lx",
+ &bus, &vendor, &product, &driver_data);
+ if (ret < 3)
+ return -EINVAL;
+
+ dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
+ if (!dynid)
+ return -ENOMEM;
+
+ dynid->id.bus = bus;
+ dynid->id.vendor = vendor;
+ dynid->id.product = product;
+ dynid->id.driver_data = driver_data;
+
+ spin_lock(&hdrv->dyn_lock);
+ list_add_tail(&dynid->list, &hdrv->dyn_list);
+ spin_unlock(&hdrv->dyn_lock);
+
+ ret = 0;
+ if (get_driver(&hdrv->driver)) {
+ ret = driver_attach(&hdrv->driver);
+ put_driver(&hdrv->driver);
+ }
+
+ return ret ? : count;
+}
+static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
+
+static void hid_free_dynids(struct hid_driver *hdrv)
+{
+ struct hid_dynid *dynid, *n;
+
+ spin_lock(&hdrv->dyn_lock);
+ list_for_each_entry_safe(dynid, n, &hdrv->dyn_list, list) {
+ list_del(&dynid->list);
+ kfree(dynid);
+ }
+ spin_unlock(&hdrv->dyn_lock);
+}
+
+static const struct hid_device_id *hid_match_device(struct hid_device *hdev,
+ struct hid_driver *hdrv)
+{
+ struct hid_dynid *dynid;
+
+ spin_lock(&hdrv->dyn_lock);
+ list_for_each_entry(dynid, &hdrv->dyn_list, list) {
+ if (hid_match_one_id(hdev, &dynid->id)) {
+ spin_unlock(&hdrv->dyn_lock);
+ return &dynid->id;
+ }
+ }
+ spin_unlock(&hdrv->dyn_lock);
+
+ return hid_match_id(hdev, hdrv->id_table);
+}
+
static int hid_bus_match(struct device *dev, struct device_driver *drv)
{
struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver);
struct hid_device *hdev = container_of(dev, struct hid_device, dev);
- if (!hid_match_id(hdev, hdrv->id_table))
+ if (!hid_match_device(hdev, hdrv))
return 0;
/* generic wants all non-blacklisted */
@@ -1332,7 +1410,7 @@ static int hid_device_probe(struct device *dev)
int ret = 0;
if (!hdev->driver) {
- id = hid_match_id(hdev, hdrv->id_table);
+ id = hid_match_device(hdev, hdrv);
if (id == NULL)
return -ENODEV;
@@ -1420,6 +1498,7 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_DEALEXTREAME, USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
@@ -1577,6 +1656,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
{ }
@@ -1618,9 +1700,10 @@ int hid_add_device(struct hid_device *hdev)
if (hid_ignore(hdev))
return -ENODEV;
- /* XXX hack, any other cleaner solution < 20 bus_id bytes? */
- sprintf(hdev->dev.bus_id, "%04X:%04X:%04X.%04X", hdev->bus,
- hdev->vendor, hdev->product, atomic_inc_return(&id));
+ /* XXX hack, any other cleaner solution after the driver core
+ * is converted to allow more than 20 bytes as the device name? */
+ dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus,
+ hdev->vendor, hdev->product, atomic_inc_return(&id));
ret = device_add(&hdev->dev);
if (!ret)
@@ -1695,18 +1778,33 @@ EXPORT_SYMBOL_GPL(hid_destroy_device);
int __hid_register_driver(struct hid_driver *hdrv, struct module *owner,
const char *mod_name)
{
+ int ret;
+
hdrv->driver.name = hdrv->name;
hdrv->driver.bus = &hid_bus_type;
hdrv->driver.owner = owner;
hdrv->driver.mod_name = mod_name;
- return driver_register(&hdrv->driver);
+ INIT_LIST_HEAD(&hdrv->dyn_list);
+ spin_lock_init(&hdrv->dyn_lock);
+
+ ret = driver_register(&hdrv->driver);
+ if (ret)
+ return ret;
+
+ ret = driver_create_file(&hdrv->driver, &driver_attr_new_id);
+ if (ret)
+ driver_unregister(&hdrv->driver);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(__hid_register_driver);
void hid_unregister_driver(struct hid_driver *hdrv)
{
+ driver_remove_file(&hdrv->driver, &driver_attr_new_id);
driver_unregister(&hdrv->driver);
+ hid_free_dynids(hdrv);
}
EXPORT_SYMBOL_GPL(hid_unregister_driver);
diff --git a/drivers/hid/hid-dell.c b/drivers/hid/hid-dell.c
deleted file mode 100644
index f5474300b83..00000000000
--- a/drivers/hid/hid-dell.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * HID driver for some dell "special" devices
- *
- * Copyright (c) 1999 Andreas Gal
- * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
- * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
- * Copyright (c) 2006-2007 Jiri Kosina
- * Copyright (c) 2007 Paul Walmsley
- * Copyright (c) 2008 Jiri Slaby
- */
-
-/*
- * 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/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-
-#include "hid-ids.h"
-
-static int dell_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
- int ret;
-
- ret = hid_parse(hdev);
- if (ret) {
- dev_err(&hdev->dev, "parse failed\n");
- goto err_free;
- }
-
- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- if (ret) {
- dev_err(&hdev->dev, "hw start failed\n");
- goto err_free;
- }
-
- usbhid_set_leds(hdev);
-
- return 0;
-err_free:
- return ret;
-}
-
-static const struct hid_device_id dell_devices[] = {
- { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
- { HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) },
- { }
-};
-MODULE_DEVICE_TABLE(hid, dell_devices);
-
-static struct hid_driver dell_driver = {
- .name = "dell",
- .id_table = dell_devices,
- .probe = dell_probe,
-};
-
-static int dell_init(void)
-{
- return hid_register_driver(&dell_driver);
-}
-
-static void dell_exit(void)
-{
- hid_unregister_driver(&dell_driver);
-}
-
-module_init(dell_init);
-module_exit(dell_exit);
-MODULE_LICENSE("GPL");
-
-HID_COMPAT_LOAD_DRIVER(dell);
diff --git a/drivers/hid/hid-dummy.c b/drivers/hid/hid-dummy.c
index e148f86fb58..b4cc0f743d6 100644
--- a/drivers/hid/hid-dummy.c
+++ b/drivers/hid/hid-dummy.c
@@ -43,6 +43,9 @@ static int __init hid_dummy_init(void)
#ifdef CONFIG_HID_MONTEREY_MODULE
HID_COMPAT_CALL_DRIVER(monterey);
#endif
+#ifdef CONFIG_HID_NTRIG_MODULE
+ HID_COMPAT_CALL_DRIVER(ntrig);
+#endif
#ifdef CONFIG_HID_PANTHERLORD_MODULE
HID_COMPAT_CALL_DRIVER(pantherlord);
#endif
@@ -58,6 +61,9 @@ static int __init hid_dummy_init(void)
#ifdef CONFIG_HID_SUNPLUS_MODULE
HID_COMPAT_CALL_DRIVER(sunplus);
#endif
+#ifdef CONFIG_GREENASIA_FF_MODULE
+ HID_COMPAT_CALL_DRIVER(greenasia);
+#endif
#ifdef CONFIG_THRUSTMASTER_FF_MODULE
HID_COMPAT_CALL_DRIVER(thrustmaster);
#endif
diff --git a/drivers/hid/hid-gaff.c b/drivers/hid/hid-gaff.c
new file mode 100644
index 00000000000..71211f6a4f0
--- /dev/null
+++ b/drivers/hid/hid-gaff.c
@@ -0,0 +1,185 @@
+/*
+ * Force feedback support for GreenAsia (Product ID 0x12) based devices
+ *
+ * The devices are distributed under various names and the same USB device ID
+ * can be used in many game controllers.
+ *
+ *
+ * 0e8f:0012 "GreenAsia Inc. USB Joystick "
+ * - tested with MANTA Warior MM816 and SpeedLink Strike2 SL-6635.
+ *
+ * Copyright (c) 2008 Lukasz Lubojanski <lukasz@lubojanski.info>
+ */
+
+/*
+ * 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
+ */
+
+#include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/hid.h>
+#include "hid-ids.h"
+#include "usbhid/usbhid.h"
+
+struct gaff_device {
+ struct hid_report *report;
+};
+
+static int hid_gaff_play(struct input_dev *dev, void *data,
+ struct ff_effect *effect)
+{
+ struct hid_device *hid = input_get_drvdata(dev);
+ struct gaff_device *gaff = data;
+ int left, right;
+
+ left = effect->u.rumble.strong_magnitude;
+ right = effect->u.rumble.weak_magnitude;
+
+ dbg_hid("called with 0x%04x 0x%04x", left, right);
+
+ left = left * 0xfe / 0xffff;
+ right = right * 0xfe / 0xffff;
+
+ gaff->report->field[0]->value[0] = 0x51;
+ gaff->report->field[0]->value[1] = 0x0;
+ gaff->report->field[0]->value[2] = right;
+ gaff->report->field[0]->value[3] = 0;
+ gaff->report->field[0]->value[4] = left;
+ gaff->report->field[0]->value[5] = 0;
+ dbg_hid("running with 0x%02x 0x%02x", left, right);
+ usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
+
+ gaff->report->field[0]->value[0] = 0xfa;
+ gaff->report->field[0]->value[1] = 0xfe;
+ gaff->report->field[0]->value[2] = 0x0;
+ gaff->report->field[0]->value[4] = 0x0;
+
+ usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
+
+ return 0;
+}
+
+static int gaff_init(struct hid_device *hid)
+{
+ struct gaff_device *gaff;
+ struct hid_report *report;
+ struct hid_input *hidinput = list_entry(hid->inputs.next,
+ struct hid_input, list);
+ struct list_head *report_list =
+ &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+ struct list_head *report_ptr = report_list;
+ struct input_dev *dev = hidinput->input;
+ int error;
+
+ if (list_empty(report_list)) {
+ dev_err(&hid->dev, "no output reports found\n");
+ return -ENODEV;
+ }
+
+ report_ptr = report_ptr->next;
+
+ report = list_entry(report_ptr, struct hid_report, list);
+ if (report->maxfield < 1) {
+ dev_err(&hid->dev, "no fields in the report\n");
+ return -ENODEV;
+ }
+
+ if (report->field[0]->report_count < 6) {
+ dev_err(&hid->dev, "not enough values in the field\n");
+ return -ENODEV;
+ }
+
+ gaff = kzalloc(sizeof(struct gaff_device), GFP_KERNEL);
+ if (!gaff)
+ return -ENOMEM;
+
+ set_bit(FF_RUMBLE, dev->ffbit);
+
+ error = input_ff_create_memless(dev, gaff, hid_gaff_play);
+ if (error) {
+ kfree(gaff);
+ return error;
+ }
+
+ gaff->report = report;
+ gaff->report->field[0]->value[0] = 0x51;
+ gaff->report->field[0]->value[1] = 0x00;
+ gaff->report->field[0]->value[2] = 0x00;
+ gaff->report->field[0]->value[3] = 0x00;
+ usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
+
+ gaff->report->field[0]->value[0] = 0xfa;
+ gaff->report->field[0]->value[1] = 0xfe;
+
+ usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
+
+ dev_info(&hid->dev, "Force Feedback for GreenAsia 0x12"
+ " devices by Lukasz Lubojanski <lukasz@lubojanski.info>\n");
+
+ return 0;
+}
+
+static int ga_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ int ret;
+
+ dev_dbg(&hdev->dev, "Greenasia HID hardware probe...");
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "parse failed\n");
+ goto err;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+ if (ret) {
+ dev_err(&hdev->dev, "hw start failed\n");
+ goto err;
+ }
+
+ gaff_init(hdev);
+
+ return 0;
+err:
+ return ret;
+}
+
+static const struct hid_device_id ga_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012), },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, ga_devices);
+
+static struct hid_driver ga_driver = {
+ .name = "greenasia",
+ .id_table = ga_devices,
+ .probe = ga_probe,
+};
+
+static int __init ga_init(void)
+{
+ return hid_register_driver(&ga_driver);
+}
+
+static void __exit ga_exit(void)
+{
+ hid_unregister_driver(&ga_driver);
+}
+
+module_init(ga_init);
+module_exit(ga_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(greenasia);
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 39289699c32..acc1abc834a 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -107,9 +107,6 @@
#define USB_VENDOR_ID_BELKIN 0x050d
#define USB_DEVICE_ID_FLIP_KVM 0x3201
-#define USB_VENDOR_ID_BRIGHT 0x1241
-#define USB_DEVICE_ID_BRIGHT_ABNT2 0x1503
-
#define USB_VENDOR_ID_BERKSHIRE 0x0c98
#define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140
@@ -141,9 +138,8 @@
#define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61
#define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64
-#define USB_VENDOR_ID_DELL 0x413c
-#define USB_DEVICE_ID_DELL_W7658 0x2005
-#define USB_DEVICE_ID_DELL_SK8115 0x2105
+#define USB_VENDOR_ID_DEALEXTREAME 0x10c5
+#define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701 0x819a
#define USB_VENDOR_ID_DELORME 0x1163
#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
@@ -167,9 +163,6 @@
#define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc
-#define USB_VENDOR_ID_GENERIC_13BA 0x13ba
-#define USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE 0x0017
-
#define USB_VENDOR_ID_GLAB 0x06c2
#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038
#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039
@@ -292,7 +285,6 @@
#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294
#define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295
#define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a
-#define USB_DEVICE_ID_LOGITECH_KBD 0xc311
#define USB_DEVICE_ID_S510_RECEIVER 0xc50c
#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512
@@ -339,6 +331,9 @@
#define USB_VENDOR_ID_NEC 0x073e
#define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301
+#define USB_VENDOR_ID_NTRIG 0x1b96
+#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001
+
#define USB_VENDOR_ID_ONTRAK 0x0a07
#define USB_DEVICE_ID_ONTRAK_ADU100 0x0064
@@ -383,9 +378,15 @@
#define USB_VENDOR_ID_TOPMAX 0x0663
#define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103
+#define USB_VENDOR_ID_TOPSEED 0x0766
+#define USB_DEVICE_ID_TOPSEED_CYBERLINK 0x0204
+
#define USB_VENDOR_ID_TURBOX 0x062a
#define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201
+#define USB_VENDOR_ID_UCLOGIC 0x5543
+#define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042
+
#define USB_VENDOR_ID_VERNIER 0x08f7
#define USB_DEVICE_ID_VERNIER_LABPRO 0x0001
#define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index 2bae340eafe..83e07c9f414 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -26,7 +26,6 @@
#define LG_RDESC 0x001
#define LG_BAD_RELATIVE_KEYS 0x002
#define LG_DUPLICATE_USAGES 0x004
-#define LG_RESET_LEDS 0x008
#define LG_EXPANDED_KEYMAP 0x010
#define LG_IGNORE_DOUBLED_WHEEL 0x020
#define LG_WIRELESS 0x040
@@ -248,9 +247,6 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
goto err_free;
}
- if (quirks & LG_RESET_LEDS)
- usbhid_set_leds(hdev);
-
if (quirks & LG_FF)
lgff_init(hdev);
if (quirks & LG_FF2)
@@ -279,9 +275,6 @@ static const struct hid_device_id lg_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI),
.driver_data = LG_DUPLICATE_USAGES },
- { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD),
- .driver_data = LG_RESET_LEDS },
-
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD),
.driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500),
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
new file mode 100644
index 00000000000..db44fbd7bdf
--- /dev/null
+++ b/drivers/hid/hid-ntrig.c
@@ -0,0 +1,82 @@
+/*
+ * HID driver for some ntrig "special" devices
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ * Copyright (c) 2008 Jiri Slaby
+ * Copyright (c) 2008 Rafi Rubin
+ *
+ */
+
+/*
+ * 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define NTRIG_DUPLICATE_USAGES 0x001
+
+#define nt_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
+ EV_KEY, (c))
+
+static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if ((usage->hid & HID_USAGE_PAGE) == HID_UP_DIGITIZER &&
+ (usage->hid & 0xff) == 0x47) {
+ nt_map_key_clear(BTN_TOOL_DOUBLETAP);
+ return 1;
+ }
+ return 0;
+}
+
+static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if (usage->type == EV_KEY || usage->type == EV_REL
+ || usage->type == EV_ABS)
+ clear_bit(usage->code, *bit);
+
+ return 0;
+}
+static const struct hid_device_id ntrig_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN),
+ .driver_data = NTRIG_DUPLICATE_USAGES },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, ntrig_devices);
+
+static struct hid_driver ntrig_driver = {
+ .name = "ntrig",
+ .id_table = ntrig_devices,
+ .input_mapping = ntrig_input_mapping,
+ .input_mapped = ntrig_input_mapped,
+};
+
+static int ntrig_init(void)
+{
+ return hid_register_driver(&ntrig_driver);
+}
+
+static void ntrig_exit(void)
+{
+ hid_unregister_driver(&ntrig_driver);
+}
+
+module_init(ntrig_init);
+module_exit(ntrig_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(ntrig);
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 86e563b8d64..dd5a3979a4d 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -102,7 +102,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
}
ret = sony_set_operational(hdev);
- if (ret)
+ if (ret < 0)
goto err_stop;
return 0;
diff --git a/drivers/hid/hid-topseed.c b/drivers/hid/hid-topseed.c
new file mode 100644
index 00000000000..cca64a0564a
--- /dev/null
+++ b/drivers/hid/hid-topseed.c
@@ -0,0 +1,77 @@
+/*
+ * HID driver for TopSeed Cyberlink remote
+ *
+ * Copyright (c) 2008 Lev Babiev
+ * based on hid-cherry driver
+ */
+
+/*
+ * 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define ts_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
+ EV_KEY, (c))
+static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if ((usage->hid & HID_USAGE_PAGE) != 0x0ffbc0000)
+ return 0;
+
+ switch (usage->hid & HID_USAGE) {
+ case 0x00d: ts_map_key_clear(KEY_HOME); break;
+ case 0x024: ts_map_key_clear(KEY_MENU); break;
+ case 0x025: ts_map_key_clear(KEY_TV); break;
+ case 0x048: ts_map_key_clear(KEY_RED); break;
+ case 0x047: ts_map_key_clear(KEY_GREEN); break;
+ case 0x049: ts_map_key_clear(KEY_YELLOW); break;
+ case 0x04a: ts_map_key_clear(KEY_BLUE); break;
+ case 0x04b: ts_map_key_clear(KEY_ANGLE); break;
+ case 0x04c: ts_map_key_clear(KEY_LANGUAGE); break;
+ case 0x04d: ts_map_key_clear(KEY_SUBTITLE); break;
+ case 0x031: ts_map_key_clear(KEY_AUDIO); break;
+ case 0x032: ts_map_key_clear(KEY_TEXT); break;
+ case 0x033: ts_map_key_clear(KEY_CHANNEL); break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static const struct hid_device_id ts_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, ts_devices);
+
+static struct hid_driver ts_driver = {
+ .name = "topseed",
+ .id_table = ts_devices,
+ .input_mapping = ts_input_mapping,
+};
+
+static int ts_init(void)
+{
+ return hid_register_driver(&ts_driver);
+}
+
+static void ts_exit(void)
+{
+ hid_unregister_driver(&ts_driver);
+}
+
+module_init(ts_init);
+module_exit(ts_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(topseed);
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 7685ae6808c..73244962897 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -208,7 +208,7 @@ static int hidraw_release(struct inode * inode, struct file * file)
list_del(&list->node);
dev = hidraw_table[minor];
- if (!dev->open--) {
+ if (!--dev->open) {
if (list->hidraw->exist)
dev->hid->ll_driver->close(dev->hid);
else
@@ -265,6 +265,34 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
break;
}
default:
+ {
+ struct hid_device *hid = dev->hid;
+ if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ)
+ return -EINVAL;
+
+ if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) {
+ int len;
+ if (!hid->name)
+ return 0;
+ len = strlen(hid->name) + 1;
+ if (len > _IOC_SIZE(cmd))
+ len = _IOC_SIZE(cmd);
+ return copy_to_user(user_arg, hid->name, len) ?
+ -EFAULT : len;
+ }
+
+ if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) {
+ int len;
+ if (!hid->phys)
+ return 0;
+ len = strlen(hid->phys) + 1;
+ if (len > _IOC_SIZE(cmd))
+ len = _IOC_SIZE(cmd);
+ return copy_to_user(user_arg, hid->phys, len) ?
+ -EFAULT : len;
+ }
+ }
+
ret = -ENOTTY;
}
unlock_kernel();
@@ -329,7 +357,7 @@ int hidraw_connect(struct hid_device *hid)
goto out;
}
- dev->dev = device_create(hidraw_class, NULL, MKDEV(hidraw_major, minor),
+ dev->dev = device_create(hidraw_class, &hid->dev, MKDEV(hidraw_major, minor),
NULL, "%s%d", "hidraw", minor);
if (IS_ERR(dev->dev)) {
diff --git a/drivers/hid/usbhid/Kconfig b/drivers/hid/usbhid/Kconfig
index 5d9aa95fc3e..4edb3bef94a 100644
--- a/drivers/hid/usbhid/Kconfig
+++ b/drivers/hid/usbhid/Kconfig
@@ -45,7 +45,7 @@ config USB_HIDDEV
If unsure, say Y.
menu "USB HID Boot Protocol drivers"
- depends on USB!=n && USB_HID!=y
+ depends on USB!=n && USB_HID!=y && EMBEDDED
config USB_KBD
tristate "USB HIDBP Keyboard (simple Boot) support"
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 606369ea24c..03cb494af1c 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -4,7 +4,7 @@
* Copyright (c) 1999 Andreas Gal
* Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
- * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2006-2008 Jiri Kosina
*/
/*
@@ -641,9 +641,7 @@ static void hid_find_max_report(struct hid_device *hid, unsigned int type,
unsigned int size;
list_for_each_entry(report, &hid->report_enum[type].report_list, list) {
- size = ((report->size - 1) >> 3) + 1;
- if (type == HID_INPUT_REPORT && hid->report_enum[type].numbered)
- size++;
+ size = ((report->size - 1) >> 3) + 1 + hid->report_enum[type].numbered;
if (*max < size)
*max = size;
}
@@ -653,13 +651,16 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
{
struct usbhid_device *usbhid = hid->driver_data;
- if (!(usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->inbuf_dma)))
- return -1;
- if (!(usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->outbuf_dma)))
- return -1;
- if (!(usbhid->cr = usb_buffer_alloc(dev, sizeof(*(usbhid->cr)), GFP_ATOMIC, &usbhid->cr_dma)))
- return -1;
- if (!(usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->ctrlbuf_dma)))
+ usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
+ &usbhid->inbuf_dma);
+ usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
+ &usbhid->outbuf_dma);
+ usbhid->cr = usb_buffer_alloc(dev, sizeof(*usbhid->cr), GFP_KERNEL,
+ &usbhid->cr_dma);
+ usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
+ &usbhid->ctrlbuf_dma);
+ if (!usbhid->inbuf || !usbhid->outbuf || !usbhid->cr ||
+ !usbhid->ctrlbuf)
return -1;
return 0;
@@ -807,7 +808,7 @@ static int usbhid_start(struct hid_device *hid)
int interval;
endpoint = &interface->endpoint[n].desc;
- if ((endpoint->bmAttributes & 3) != 3) /* Not an interrupt endpoint */
+ if (!usb_endpoint_xfer_int(endpoint))
continue;
interval = endpoint->bInterval;
@@ -876,6 +877,15 @@ static int usbhid_start(struct hid_device *hid)
set_bit(HID_STARTED, &usbhid->iofl);
+ /* Some keyboards don't work until their LEDs have been set.
+ * Since BIOSes do set the LEDs, it must be safe for any device
+ * that supports the keyboard boot protocol.
+ */
+ if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT &&
+ interface->desc.bInterfaceProtocol ==
+ USB_INTERFACE_PROTOCOL_KEYBOARD)
+ usbhid_set_leds(hid);
+
return 0;
fail:
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 47ebe045f9b..4391717d251 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -54,6 +54,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 83e851a5ed3..6a98f9f572b 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -49,6 +49,7 @@
struct hiddev {
int exist;
int open;
+ struct mutex existancelock;
wait_queue_head_t wait;
struct hid_device *hid;
struct list_head list;
@@ -63,6 +64,7 @@ struct hiddev_list {
struct fasync_struct *fasync;
struct hiddev *hiddev;
struct list_head node;
+ struct mutex thread_lock;
};
static struct hiddev *hiddev_table[HIDDEV_MINORS];
@@ -264,29 +266,48 @@ static int hiddev_release(struct inode * inode, struct file * file)
static int hiddev_open(struct inode *inode, struct file *file)
{
struct hiddev_list *list;
- unsigned long flags;
+ int res;
int i = iminor(inode) - HIDDEV_MINOR_BASE;
- if (i >= HIDDEV_MINORS || !hiddev_table[i])
+ if (i >= HIDDEV_MINORS || i < 0 || !hiddev_table[i])
return -ENODEV;
if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL)))
return -ENOMEM;
+ mutex_init(&list->thread_lock);
list->hiddev = hiddev_table[i];
- spin_lock_irqsave(&list->hiddev->list_lock, flags);
- list_add_tail(&list->node, &hiddev_table[i]->list);
- spin_unlock_irqrestore(&list->hiddev->list_lock, flags);
file->private_data = list;
- if (!list->hiddev->open++)
- if (list->hiddev->exist)
- usbhid_open(hiddev_table[i]->hid);
+ /*
+ * no need for locking because the USB major number
+ * is shared which usbcore guards against disconnect
+ */
+ if (list->hiddev->exist) {
+ if (!list->hiddev->open++) {
+ res = usbhid_open(hiddev_table[i]->hid);
+ if (res < 0) {
+ res = -EIO;
+ goto bail;
+ }
+ }
+ } else {
+ res = -ENODEV;
+ goto bail;
+ }
+
+ spin_lock_irq(&list->hiddev->list_lock);
+ list_add_tail(&list->node, &hiddev_table[i]->list);
+ spin_unlock_irq(&list->hiddev->list_lock);
return 0;
+bail:
+ file->private_data = NULL;
+ kfree(list->hiddev);
+ return res;
}
/*
@@ -305,7 +326,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
DECLARE_WAITQUEUE(wait, current);
struct hiddev_list *list = file->private_data;
int event_size;
- int retval = 0;
+ int retval;
event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ?
sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event);
@@ -313,10 +334,14 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
if (count < event_size)
return 0;
+ /* lock against other threads */
+ retval = mutex_lock_interruptible(&list->thread_lock);
+ if (retval)
+ return -ERESTARTSYS;
+
while (retval == 0) {
if (list->head == list->tail) {
- add_wait_queue(&list->hiddev->wait, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
+ prepare_to_wait(&list->hiddev->wait, &wait, TASK_INTERRUPTIBLE);
while (list->head == list->tail) {
if (file->f_flags & O_NONBLOCK) {
@@ -332,35 +357,45 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
break;
}
+ /* let O_NONBLOCK tasks run */
+ mutex_unlock(&list->thread_lock);
schedule();
+ if (mutex_lock_interruptible(&list->thread_lock))
+ return -EINTR;
set_current_state(TASK_INTERRUPTIBLE);
}
+ finish_wait(&list->hiddev->wait, &wait);
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&list->hiddev->wait, &wait);
}
- if (retval)
+ if (retval) {
+ mutex_unlock(&list->thread_lock);
return retval;
+ }
while (list->head != list->tail &&
retval + event_size <= count) {
if ((list->flags & HIDDEV_FLAG_UREF) == 0) {
- if (list->buffer[list->tail].field_index !=
- HID_FIELD_INDEX_NONE) {
+ if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE) {
struct hiddev_event event;
+
event.hid = list->buffer[list->tail].usage_code;
event.value = list->buffer[list->tail].value;
- if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event)))
+ if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event))) {
+ mutex_unlock(&list->thread_lock);
return -EFAULT;
+ }
retval += sizeof(struct hiddev_event);
}
} else {
if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE ||
(list->flags & HIDDEV_FLAG_REPORT) != 0) {
- if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref)))
+
+ if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref))) {
+ mutex_unlock(&list->thread_lock);
return -EFAULT;
+ }
retval += sizeof(struct hiddev_usage_ref);
}
}
@@ -368,6 +403,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
}
}
+ mutex_unlock(&list->thread_lock);
return retval;
}
@@ -555,7 +591,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
struct hid_field *field;
struct usbhid_device *usbhid = hid->driver_data;
void __user *user_arg = (void __user *)arg;
- int i;
+ int i, r;
/* Called without BKL by compat methods so no BKL taken */
@@ -619,10 +655,22 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
case HIDIOCGSTRING:
- return hiddev_ioctl_string(hiddev, cmd, user_arg);
+ mutex_lock(&hiddev->existancelock);
+ if (!hiddev->exist)
+ r = hiddev_ioctl_string(hiddev, cmd, user_arg);
+ else
+ r = -ENODEV;
+ mutex_unlock(&hiddev->existancelock);
+ return r;
case HIDIOCINITREPORT:
+ mutex_lock(&hiddev->existancelock);
+ if (!hiddev->exist) {
+ mutex_unlock(&hiddev->existancelock);
+ return -ENODEV;
+ }
usbhid_init_reports(hid);
+ mutex_unlock(&hiddev->existancelock);
return 0;
@@ -636,8 +684,12 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
return -EINVAL;
- usbhid_submit_report(hid, report, USB_DIR_IN);
- usbhid_wait_io(hid);
+ mutex_lock(&hiddev->existancelock);
+ if (hiddev->exist) {
+ usbhid_submit_report(hid, report, USB_DIR_IN);
+ usbhid_wait_io(hid);
+ }
+ mutex_unlock(&hiddev->existancelock);
return 0;
@@ -651,8 +703,12 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
return -EINVAL;
- usbhid_submit_report(hid, report, USB_DIR_OUT);
- usbhid_wait_io(hid);
+ mutex_lock(&hiddev->existancelock);
+ if (hiddev->exist) {
+ usbhid_submit_report(hid, report, USB_DIR_OUT);
+ usbhid_wait_io(hid);
+ }
+ mutex_unlock(&hiddev->existancelock);
return 0;
@@ -710,7 +766,13 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case HIDIOCGUSAGES:
case HIDIOCSUSAGES:
case HIDIOCGCOLLECTIONINDEX:
- return hiddev_ioctl_usage(hiddev, cmd, user_arg);
+ mutex_lock(&hiddev->existancelock);
+ if (hiddev->exist)
+ r = hiddev_ioctl_usage(hiddev, cmd, user_arg);
+ else
+ r = -ENODEV;
+ mutex_unlock(&hiddev->existancelock);
+ return r;
case HIDIOCGCOLLECTIONINFO:
if (copy_from_user(&cinfo, user_arg, sizeof(cinfo)))
@@ -808,23 +870,22 @@ int hiddev_connect(struct hid_device *hid, unsigned int force)
if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL)))
return -1;
- retval = usb_register_dev(usbhid->intf, &hiddev_class);
- if (retval) {
- err_hid("Not able to get a minor for this device.");
- kfree(hiddev);
- return -1;
- }
-
init_waitqueue_head(&hiddev->wait);
INIT_LIST_HEAD(&hiddev->list);
spin_lock_init(&hiddev->list_lock);
+ mutex_init(&hiddev->existancelock);
hiddev->hid = hid;
hiddev->exist = 1;
- hid->minor = usbhid->intf->minor;
- hid->hiddev = hiddev;
-
- hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
+ retval = usb_register_dev(usbhid->intf, &hiddev_class);
+ if (retval) {
+ err_hid("Not able to get a minor for this device.");
+ kfree(hiddev);
+ return -1;
+ } else {
+ hid->minor = usbhid->intf->minor;
+ hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
+ }
return 0;
}
@@ -839,7 +900,9 @@ void hiddev_disconnect(struct hid_device *hid)
struct hiddev *hiddev = hid->hiddev;
struct usbhid_device *usbhid = hid->driver_data;
+ mutex_lock(&hiddev->existancelock);
hiddev->exist = 0;
+ mutex_unlock(&hiddev->existancelock);
hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL;
usb_deregister_dev(usbhid->intf, &hiddev_class);
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
index 332abcdf995..9eb30564be9 100644
--- a/drivers/hid/usbhid/usbhid.h
+++ b/drivers/hid/usbhid/usbhid.h
@@ -40,6 +40,16 @@ int usbhid_open(struct hid_device *hid);
void usbhid_init_reports(struct hid_device *hid);
void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir);
+/* iofl flags */
+#define HID_CTRL_RUNNING 1
+#define HID_OUT_RUNNING 2
+#define HID_IN_RUNNING 3
+#define HID_RESET_PENDING 4
+#define HID_SUSPENDED 5
+#define HID_CLEAR_HALT 6
+#define HID_DISCONNECTED 7
+#define HID_STARTED 8
+
/*
* USB-specific HID struct, to be pointed to
* from struct hid_device->driver_data
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 608038d64f8..be8ee2cac8b 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -2,13 +2,16 @@
* TI OMAP I2C master mode driver
*
* Copyright (C) 2003 MontaVista Software, Inc.
- * Copyright (C) 2004 Texas Instruments.
- *
- * Updated to work with multiple I2C interfaces on 24xx by
- * Tony Lindgren <tony@atomide.com> and Imre Deak <imre.deak@nokia.com>
* Copyright (C) 2005 Nokia Corporation
+ * Copyright (C) 2004 - 2007 Texas Instruments.
*
- * Cleaned up by Juha Yrjölä <juha.yrjola@nokia.com>
+ * Originally written by MontaVista Software, Inc.
+ * Additional contributions by:
+ * Tony Lindgren <tony@atomide.com>
+ * Imre Deak <imre.deak@nokia.com>
+ * Juha Yrjölä <juha.yrjola@solidboot.com>
+ * Syed Khasim <x0khasim@ti.com>
+ * Nishant Menon <nm@ti.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
@@ -33,8 +36,14 @@
#include <linux/completion.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/io.h>
+
+/* I2C controller revisions */
+#define OMAP_I2C_REV_2 0x20
-#include <asm/io.h>
+/* I2C controller revisions present on specific hardware */
+#define OMAP_I2C_REV_ON_2430 0x36
+#define OMAP_I2C_REV_ON_3430 0x3C
/* timeout waiting for the controller to respond */
#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
@@ -43,6 +52,8 @@
#define OMAP_I2C_IE_REG 0x04
#define OMAP_I2C_STAT_REG 0x08
#define OMAP_I2C_IV_REG 0x0c
+/* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */
+#define OMAP_I2C_WE_REG 0x0c
#define OMAP_I2C_SYSS_REG 0x10
#define OMAP_I2C_BUF_REG 0x14
#define OMAP_I2C_CNT_REG 0x18
@@ -55,8 +66,11 @@
#define OMAP_I2C_SCLL_REG 0x34
#define OMAP_I2C_SCLH_REG 0x38
#define OMAP_I2C_SYSTEST_REG 0x3c
+#define OMAP_I2C_BUFSTAT_REG 0x40
/* I2C Interrupt Enable Register (OMAP_I2C_IE): */
+#define OMAP_I2C_IE_XDR (1 << 14) /* TX Buffer drain int enable */
+#define OMAP_I2C_IE_RDR (1 << 13) /* RX Buffer drain int enable */
#define OMAP_I2C_IE_XRDY (1 << 4) /* TX data ready int enable */
#define OMAP_I2C_IE_RRDY (1 << 3) /* RX data ready int enable */
#define OMAP_I2C_IE_ARDY (1 << 2) /* Access ready int enable */
@@ -64,7 +78,8 @@
#define OMAP_I2C_IE_AL (1 << 0) /* Arbitration lost int ena */
/* I2C Status Register (OMAP_I2C_STAT): */
-#define OMAP_I2C_STAT_SBD (1 << 15) /* Single byte data */
+#define OMAP_I2C_STAT_XDR (1 << 14) /* TX Buffer draining */
+#define OMAP_I2C_STAT_RDR (1 << 13) /* RX Buffer draining */
#define OMAP_I2C_STAT_BB (1 << 12) /* Bus busy */
#define OMAP_I2C_STAT_ROVR (1 << 11) /* Receive overrun */
#define OMAP_I2C_STAT_XUDF (1 << 10) /* Transmit underflow */
@@ -76,13 +91,34 @@
#define OMAP_I2C_STAT_NACK (1 << 1) /* No ack interrupt enable */
#define OMAP_I2C_STAT_AL (1 << 0) /* Arbitration lost int ena */
+/* I2C WE wakeup enable register */
+#define OMAP_I2C_WE_XDR_WE (1 << 14) /* TX drain wakup */
+#define OMAP_I2C_WE_RDR_WE (1 << 13) /* RX drain wakeup */
+#define OMAP_I2C_WE_AAS_WE (1 << 9) /* Address as slave wakeup*/
+#define OMAP_I2C_WE_BF_WE (1 << 8) /* Bus free wakeup */
+#define OMAP_I2C_WE_STC_WE (1 << 6) /* Start condition wakeup */
+#define OMAP_I2C_WE_GC_WE (1 << 5) /* General call wakeup */
+#define OMAP_I2C_WE_DRDY_WE (1 << 3) /* TX/RX data ready wakeup */
+#define OMAP_I2C_WE_ARDY_WE (1 << 2) /* Reg access ready wakeup */
+#define OMAP_I2C_WE_NACK_WE (1 << 1) /* No acknowledgment wakeup */
+#define OMAP_I2C_WE_AL_WE (1 << 0) /* Arbitration lost wakeup */
+
+#define OMAP_I2C_WE_ALL (OMAP_I2C_WE_XDR_WE | OMAP_I2C_WE_RDR_WE | \
+ OMAP_I2C_WE_AAS_WE | OMAP_I2C_WE_BF_WE | \
+ OMAP_I2C_WE_STC_WE | OMAP_I2C_WE_GC_WE | \
+ OMAP_I2C_WE_DRDY_WE | OMAP_I2C_WE_ARDY_WE | \
+ OMAP_I2C_WE_NACK_WE | OMAP_I2C_WE_AL_WE)
+
/* I2C Buffer Configuration Register (OMAP_I2C_BUF): */
#define OMAP_I2C_BUF_RDMA_EN (1 << 15) /* RX DMA channel enable */
+#define OMAP_I2C_BUF_RXFIF_CLR (1 << 14) /* RX FIFO Clear */
#define OMAP_I2C_BUF_XDMA_EN (1 << 7) /* TX DMA channel enable */
+#define OMAP_I2C_BUF_TXFIF_CLR (1 << 6) /* TX FIFO Clear */
/* I2C Configuration Register (OMAP_I2C_CON): */
#define OMAP_I2C_CON_EN (1 << 15) /* I2C module enable */
#define OMAP_I2C_CON_BE (1 << 14) /* Big endian mode */
+#define OMAP_I2C_CON_OPMODE_HS (1 << 12) /* High Speed support */
#define OMAP_I2C_CON_STB (1 << 11) /* Start byte mode (master) */
#define OMAP_I2C_CON_MST (1 << 10) /* Master/slave mode */
#define OMAP_I2C_CON_TRX (1 << 9) /* TX/RX mode (master only) */
@@ -91,6 +127,10 @@
#define OMAP_I2C_CON_STP (1 << 1) /* Stop cond (master only) */
#define OMAP_I2C_CON_STT (1 << 0) /* Start condition (master) */
+/* I2C SCL time value when Master */
+#define OMAP_I2C_SCLL_HSSCLL 8
+#define OMAP_I2C_SCLH_HSSCLH 8
+
/* I2C System Test Register (OMAP_I2C_SYSTEST): */
#ifdef DEBUG
#define OMAP_I2C_SYSTEST_ST_EN (1 << 15) /* System test enable */
@@ -103,17 +143,19 @@
#define OMAP_I2C_SYSTEST_SDA_O (1 << 0) /* SDA line drive out */
#endif
-/* I2C System Status register (OMAP_I2C_SYSS): */
-#define OMAP_I2C_SYSS_RDONE (1 << 0) /* Reset Done */
+/* OCP_SYSSTATUS bit definitions */
+#define SYSS_RESETDONE_MASK (1 << 0)
+
+/* OCP_SYSCONFIG bit definitions */
+#define SYSC_CLOCKACTIVITY_MASK (0x3 << 8)
+#define SYSC_SIDLEMODE_MASK (0x3 << 3)
+#define SYSC_ENAWAKEUP_MASK (1 << 2)
+#define SYSC_SOFTRESET_MASK (1 << 1)
+#define SYSC_AUTOIDLE_MASK (1 << 0)
-/* I2C System Configuration Register (OMAP_I2C_SYSC): */
-#define OMAP_I2C_SYSC_SRST (1 << 1) /* Soft Reset */
+#define SYSC_IDLEMODE_SMART 0x2
+#define SYSC_CLOCKACTIVITY_FCLK 0x2
-/* REVISIT: Use platform_data instead of module parameters */
-/* Fast Mode = 400 kHz, Standard = 100 kHz */
-static int clock = 100; /* Default: 100 kHz */
-module_param(clock, int, 0);
-MODULE_PARM_DESC(clock, "Set I2C clock in kHz: 400=fast mode (default == 100)");
struct omap_i2c_dev {
struct device *dev;
@@ -123,11 +165,17 @@ struct omap_i2c_dev {
struct clk *fclk; /* Functional clock */
struct completion cmd_complete;
struct resource *ioarea;
+ u32 speed; /* Speed of bus in Khz */
u16 cmd_err;
u8 *buf;
size_t buf_len;
struct i2c_adapter adapter;
- unsigned rev1:1;
+ u8 fifo_size; /* use as flag and value
+ * fifo_size==0 implies no fifo
+ * if set, should be trsh+1
+ */
+ u8 rev;
+ unsigned b_hw:1; /* bad h/w fixes */
unsigned idle:1;
u16 iestate; /* Saved interrupt register */
};
@@ -143,9 +191,9 @@ static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
return __raw_readw(i2c_dev->base + reg);
}
-static int omap_i2c_get_clocks(struct omap_i2c_dev *dev)
+static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev)
{
- if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
+ if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
dev->iclk = clk_get(dev->dev, "i2c_ick");
if (IS_ERR(dev->iclk)) {
dev->iclk = NULL;
@@ -178,25 +226,33 @@ static void omap_i2c_put_clocks(struct omap_i2c_dev *dev)
static void omap_i2c_unidle(struct omap_i2c_dev *dev)
{
+ WARN_ON(!dev->idle);
+
if (dev->iclk != NULL)
clk_enable(dev->iclk);
clk_enable(dev->fclk);
+ dev->idle = 0;
if (dev->iestate)
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
- dev->idle = 0;
}
static void omap_i2c_idle(struct omap_i2c_dev *dev)
{
u16 iv;
- dev->idle = 1;
+ WARN_ON(dev->idle);
+
dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
- if (dev->rev1)
- iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
- else
+ if (dev->rev < OMAP_I2C_REV_2) {
+ iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
+ } else {
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate);
+
+ /* Flush posted write before the dev->idle store occurs */
+ omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
+ }
+ dev->idle = 1;
clk_disable(dev->fclk);
if (dev->iclk != NULL)
clk_disable(dev->iclk);
@@ -204,18 +260,20 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev)
static int omap_i2c_init(struct omap_i2c_dev *dev)
{
- u16 psc = 0;
+ u16 psc = 0, scll = 0, sclh = 0;
+ u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0;
unsigned long fclk_rate = 12000000;
unsigned long timeout;
+ unsigned long internal_clk = 0;
- if (!dev->rev1) {
- omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, OMAP_I2C_SYSC_SRST);
+ if (dev->rev >= OMAP_I2C_REV_2) {
+ omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, SYSC_SOFTRESET_MASK);
/* For some reason we need to set the EN bit before the
* reset done bit gets set. */
timeout = jiffies + OMAP_I2C_TIMEOUT;
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
while (!(omap_i2c_read_reg(dev, OMAP_I2C_SYSS_REG) &
- OMAP_I2C_SYSS_RDONE)) {
+ SYSS_RESETDONE_MASK)) {
if (time_after(jiffies, timeout)) {
dev_warn(dev->dev, "timeout waiting "
"for controller reset\n");
@@ -223,6 +281,33 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
}
msleep(1);
}
+
+ /* SYSC register is cleared by the reset; rewrite it */
+ if (dev->rev == OMAP_I2C_REV_ON_2430) {
+
+ omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG,
+ SYSC_AUTOIDLE_MASK);
+
+ } else if (dev->rev >= OMAP_I2C_REV_ON_3430) {
+ u32 v;
+
+ v = SYSC_AUTOIDLE_MASK;
+ v |= SYSC_ENAWAKEUP_MASK;
+ v |= (SYSC_IDLEMODE_SMART <<
+ __ffs(SYSC_SIDLEMODE_MASK));
+ v |= (SYSC_CLOCKACTIVITY_FCLK <<
+ __ffs(SYSC_CLOCKACTIVITY_MASK));
+
+ omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, v);
+ /*
+ * Enabling all wakup sources to stop I2C freezing on
+ * WFI instruction.
+ * REVISIT: Some wkup sources might not be needed.
+ */
+ omap_i2c_write_reg(dev, OMAP_I2C_WE_REG,
+ OMAP_I2C_WE_ALL);
+
+ }
}
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
@@ -249,27 +334,65 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
psc = fclk_rate / 12000000;
}
+ if (cpu_is_omap2430() || cpu_is_omap34xx()) {
+
+ /* HSI2C controller internal clk rate should be 19.2 Mhz */
+ internal_clk = 19200;
+ fclk_rate = clk_get_rate(dev->fclk) / 1000;
+
+ /* Compute prescaler divisor */
+ psc = fclk_rate / internal_clk;
+ psc = psc - 1;
+
+ /* If configured for High Speed */
+ if (dev->speed > 400) {
+ /* For first phase of HS mode */
+ fsscll = internal_clk / (400 * 2) - 6;
+ fssclh = internal_clk / (400 * 2) - 6;
+
+ /* For second phase of HS mode */
+ hsscll = fclk_rate / (dev->speed * 2) - 6;
+ hssclh = fclk_rate / (dev->speed * 2) - 6;
+ } else {
+ /* To handle F/S modes */
+ fsscll = internal_clk / (dev->speed * 2) - 6;
+ fssclh = internal_clk / (dev->speed * 2) - 6;
+ }
+ scll = (hsscll << OMAP_I2C_SCLL_HSSCLL) | fsscll;
+ sclh = (hssclh << OMAP_I2C_SCLH_HSSCLH) | fssclh;
+ } else {
+ /* Program desired operating rate */
+ fclk_rate /= (psc + 1) * 1000;
+ if (psc > 2)
+ psc = 2;
+ scll = fclk_rate / (dev->speed * 2) - 7 + psc;
+ sclh = fclk_rate / (dev->speed * 2) - 7 + psc;
+ }
+
/* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc);
- /* Program desired operating rate */
- fclk_rate /= (psc + 1) * 1000;
- if (psc > 2)
- psc = 2;
+ /* SCL low and high time values */
+ omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll);
+ omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh);
- omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG,
- fclk_rate / (clock * 2) - 7 + psc);
- omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG,
- fclk_rate / (clock * 2) - 7 + psc);
+ if (dev->fifo_size)
+ /* Note: setup required fifo size - 1 */
+ omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG,
+ (dev->fifo_size - 1) << 8 | /* RTRSH */
+ OMAP_I2C_BUF_RXFIF_CLR |
+ (dev->fifo_size - 1) | /* XTRSH */
+ OMAP_I2C_BUF_TXFIF_CLR);
/* Take the I2C module out of reset: */
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
/* Enable interrupts */
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG,
- (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
- OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
- OMAP_I2C_IE_AL));
+ (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
+ OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
+ OMAP_I2C_IE_AL) | ((dev->fifo_size) ?
+ (OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0));
return 0;
}
@@ -316,20 +439,59 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len);
+ /* Clear the FIFO Buffers */
+ w = omap_i2c_read_reg(dev, OMAP_I2C_BUF_REG);
+ w |= OMAP_I2C_BUF_RXFIF_CLR | OMAP_I2C_BUF_TXFIF_CLR;
+ omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, w);
+
init_completion(&dev->cmd_complete);
dev->cmd_err = 0;
w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT;
+
+ /* High speed configuration */
+ if (dev->speed > 400)
+ w |= OMAP_I2C_CON_OPMODE_HS;
+
if (msg->flags & I2C_M_TEN)
w |= OMAP_I2C_CON_XA;
if (!(msg->flags & I2C_M_RD))
w |= OMAP_I2C_CON_TRX;
- if (stop)
+
+ if (!dev->b_hw && stop)
w |= OMAP_I2C_CON_STP;
+
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
- r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
- OMAP_I2C_TIMEOUT);
+ /*
+ * Don't write stt and stp together on some hardware.
+ */
+ if (dev->b_hw && stop) {
+ unsigned long delay = jiffies + OMAP_I2C_TIMEOUT;
+ u16 con = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
+ while (con & OMAP_I2C_CON_STT) {
+ con = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
+
+ /* Let the user know if i2c is in a bad state */
+ if (time_after(jiffies, delay)) {
+ dev_err(dev->dev, "controller timed out "
+ "waiting for start condition to finish\n");
+ return -ETIMEDOUT;
+ }
+ cpu_relax();
+ }
+
+ w |= OMAP_I2C_CON_STP;
+ w &= ~OMAP_I2C_CON_STT;
+ omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
+ }
+
+ /*
+ * REVISIT: We should abort the transfer on signals, but the bus goes
+ * into arbitration and we're currently unable to recover from it.
+ */
+ r = wait_for_completion_timeout(&dev->cmd_complete,
+ OMAP_I2C_TIMEOUT);
dev->buf_len = 0;
if (r < 0)
return r;
@@ -376,7 +538,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
omap_i2c_unidle(dev);
- if ((r = omap_i2c_wait_for_bb(dev)) < 0)
+ r = omap_i2c_wait_for_bb(dev);
+ if (r < 0)
goto out;
for (i = 0; i < num; i++) {
@@ -411,6 +574,9 @@ omap_i2c_ack_stat(struct omap_i2c_dev *dev, u16 stat)
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
}
+/* rev1 devices are apparently only on some 15xx */
+#ifdef CONFIG_ARCH_OMAP15XX
+
static irqreturn_t
omap_i2c_rev1_isr(int this_irq, void *dev_id)
{
@@ -465,6 +631,9 @@ omap_i2c_rev1_isr(int this_irq, void *dev_id)
return IRQ_HANDLED;
}
+#else
+#define omap_i2c_rev1_isr NULL
+#endif
static irqreturn_t
omap_i2c_isr(int this_irq, void *dev_id)
@@ -472,7 +641,7 @@ omap_i2c_isr(int this_irq, void *dev_id)
struct omap_i2c_dev *dev = dev_id;
u16 bits;
u16 stat, w;
- int count = 0;
+ int err, count = 0;
if (dev->idle)
return IRQ_NONE;
@@ -487,39 +656,96 @@ omap_i2c_isr(int this_irq, void *dev_id)
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
- if (stat & OMAP_I2C_STAT_ARDY) {
- omap_i2c_complete_cmd(dev, 0);
- continue;
+ err = 0;
+ if (stat & OMAP_I2C_STAT_NACK) {
+ err |= OMAP_I2C_STAT_NACK;
+ omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
+ OMAP_I2C_CON_STP);
}
- if (stat & OMAP_I2C_STAT_RRDY) {
- w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
- if (dev->buf_len) {
- *dev->buf++ = w;
- dev->buf_len--;
+ if (stat & OMAP_I2C_STAT_AL) {
+ dev_err(dev->dev, "Arbitration lost\n");
+ err |= OMAP_I2C_STAT_AL;
+ }
+ if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK |
+ OMAP_I2C_STAT_AL))
+ omap_i2c_complete_cmd(dev, err);
+ if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) {
+ u8 num_bytes = 1;
+ if (dev->fifo_size) {
+ if (stat & OMAP_I2C_STAT_RRDY)
+ num_bytes = dev->fifo_size;
+ else
+ num_bytes = omap_i2c_read_reg(dev,
+ OMAP_I2C_BUFSTAT_REG);
+ }
+ while (num_bytes) {
+ num_bytes--;
+ w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
if (dev->buf_len) {
- *dev->buf++ = w >> 8;
+ *dev->buf++ = w;
dev->buf_len--;
+ /* Data reg from 2430 is 8 bit wide */
+ if (!cpu_is_omap2430() &&
+ !cpu_is_omap34xx()) {
+ if (dev->buf_len) {
+ *dev->buf++ = w >> 8;
+ dev->buf_len--;
+ }
+ }
+ } else {
+ if (stat & OMAP_I2C_STAT_RRDY)
+ dev_err(dev->dev,
+ "RRDY IRQ while no data"
+ " requested\n");
+ if (stat & OMAP_I2C_STAT_RDR)
+ dev_err(dev->dev,
+ "RDR IRQ while no data"
+ " requested\n");
+ break;
}
- } else
- dev_err(dev->dev, "RRDY IRQ while no data "
- "requested\n");
- omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RRDY);
+ }
+ omap_i2c_ack_stat(dev,
+ stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR));
continue;
}
- if (stat & OMAP_I2C_STAT_XRDY) {
- w = 0;
- if (dev->buf_len) {
- w = *dev->buf++;
- dev->buf_len--;
+ if (stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)) {
+ u8 num_bytes = 1;
+ if (dev->fifo_size) {
+ if (stat & OMAP_I2C_STAT_XRDY)
+ num_bytes = dev->fifo_size;
+ else
+ num_bytes = omap_i2c_read_reg(dev,
+ OMAP_I2C_BUFSTAT_REG);
+ }
+ while (num_bytes) {
+ num_bytes--;
+ w = 0;
if (dev->buf_len) {
- w |= *dev->buf++ << 8;
+ w = *dev->buf++;
dev->buf_len--;
+ /* Data reg from 2430 is 8 bit wide */
+ if (!cpu_is_omap2430() &&
+ !cpu_is_omap34xx()) {
+ if (dev->buf_len) {
+ w |= *dev->buf++ << 8;
+ dev->buf_len--;
+ }
+ }
+ } else {
+ if (stat & OMAP_I2C_STAT_XRDY)
+ dev_err(dev->dev,
+ "XRDY IRQ while no "
+ "data to send\n");
+ if (stat & OMAP_I2C_STAT_XDR)
+ dev_err(dev->dev,
+ "XDR IRQ while no "
+ "data to send\n");
+ break;
}
- } else
- dev_err(dev->dev, "XRDY IRQ while no "
- "data to send\n");
- omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
- omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XRDY);
+ omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
+ }
+ omap_i2c_ack_stat(dev,
+ stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
continue;
}
if (stat & OMAP_I2C_STAT_ROVR) {
@@ -527,18 +753,9 @@ omap_i2c_isr(int this_irq, void *dev_id)
dev->cmd_err |= OMAP_I2C_STAT_ROVR;
}
if (stat & OMAP_I2C_STAT_XUDF) {
- dev_err(dev->dev, "Transmit overflow\n");
+ dev_err(dev->dev, "Transmit underflow\n");
dev->cmd_err |= OMAP_I2C_STAT_XUDF;
}
- if (stat & OMAP_I2C_STAT_NACK) {
- omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_NACK);
- omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
- OMAP_I2C_CON_STP);
- }
- if (stat & OMAP_I2C_STAT_AL) {
- dev_err(dev->dev, "Arbitration lost\n");
- omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_AL);
- }
}
return count ? IRQ_HANDLED : IRQ_NONE;
@@ -549,13 +766,15 @@ static const struct i2c_algorithm omap_i2c_algo = {
.functionality = omap_i2c_func,
};
-static int
+static int __init
omap_i2c_probe(struct platform_device *pdev)
{
struct omap_i2c_dev *dev;
struct i2c_adapter *adap;
struct resource *mem, *irq, *ioarea;
+ irq_handler_t isr;
int r;
+ u32 speed = 0;
/* NOTE: driver uses the static register mapping */
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -576,17 +795,19 @@ omap_i2c_probe(struct platform_device *pdev)
return -EBUSY;
}
- if (clock > 200)
- clock = 400; /* Fast mode */
- else
- clock = 100; /* Standard mode */
-
dev = kzalloc(sizeof(struct omap_i2c_dev), GFP_KERNEL);
if (!dev) {
r = -ENOMEM;
goto err_release_region;
}
+ if (pdev->dev.platform_data != NULL)
+ speed = *(u32 *)pdev->dev.platform_data;
+ else
+ speed = 100; /* Defualt speed */
+
+ dev->speed = speed;
+ dev->idle = 1;
dev->dev = &pdev->dev;
dev->irq = irq->start;
dev->base = ioremap(mem->start, mem->end - mem->start + 1);
@@ -602,22 +823,39 @@ omap_i2c_probe(struct platform_device *pdev)
omap_i2c_unidle(dev);
- if (cpu_is_omap15xx())
- dev->rev1 = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) < 0x20;
+ dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
+
+ if (cpu_is_omap2430() || cpu_is_omap34xx()) {
+ u16 s;
+
+ /* Set up the fifo size - Get total size */
+ s = (omap_i2c_read_reg(dev, OMAP_I2C_BUFSTAT_REG) >> 14) & 0x3;
+ dev->fifo_size = 0x8 << s;
+
+ /*
+ * Set up notification threshold as half the total available
+ * size. This is to ensure that we can handle the status on int
+ * call back latencies.
+ */
+ dev->fifo_size = (dev->fifo_size / 2);
+ dev->b_hw = 1; /* Enable hardware fixes */
+ }
/* reset ASAP, clearing any IRQs */
omap_i2c_init(dev);
- r = request_irq(dev->irq, dev->rev1 ? omap_i2c_rev1_isr : omap_i2c_isr,
- 0, pdev->name, dev);
+ isr = (dev->rev < OMAP_I2C_REV_2) ? omap_i2c_rev1_isr : omap_i2c_isr;
+ r = request_irq(dev->irq, isr, 0, pdev->name, dev);
if (r) {
dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);
goto err_unuse_clocks;
}
- r = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
+
dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n",
- pdev->id, r >> 4, r & 0xf, clock);
+ pdev->id, dev->rev >> 4, dev->rev & 0xf, dev->speed);
+
+ omap_i2c_idle(dev);
adap = &dev->adapter;
i2c_set_adapdata(adap, dev);
@@ -635,8 +873,6 @@ omap_i2c_probe(struct platform_device *pdev)
goto err_free_irq;
}
- omap_i2c_idle(dev);
-
return 0;
err_free_irq:
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index c39079f9c73..f69f91ffb46 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -35,11 +35,9 @@
#include <linux/clk.h>
#include <linux/cpufreq.h>
-#include <mach/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <mach/regs-gpio.h>
#include <plat/regs-iic.h>
#include <plat/iic.h>
@@ -64,6 +62,7 @@ struct s3c24xx_i2c {
unsigned int msg_ptr;
unsigned int tx_setup;
+ unsigned int irq;
enum s3c24xx_i2c_state state;
unsigned long clkrate;
@@ -71,7 +70,6 @@ struct s3c24xx_i2c {
void __iomem *regs;
struct clk *clk;
struct device *dev;
- struct resource *irq;
struct resource *ioarea;
struct i2c_adapter adap;
@@ -80,16 +78,7 @@ struct s3c24xx_i2c {
#endif
};
-/* default platform data to use if not supplied in the platform_device
-*/
-
-static struct s3c2410_platform_i2c s3c24xx_i2c_default_platform = {
- .flags = 0,
- .slave_addr = 0x10,
- .bus_freq = 100*1000,
- .max_freq = 400*1000,
- .sda_delay = S3C2410_IICLC_SDA_DELAY5 | S3C2410_IICLC_FILTER_ON,
-};
+/* default platform data removed, dev should always carry data. */
/* s3c24xx_i2c_is2440()
*
@@ -103,21 +92,6 @@ static inline int s3c24xx_i2c_is2440(struct s3c24xx_i2c *i2c)
return !strcmp(pdev->name, "s3c2440-i2c");
}
-
-/* s3c24xx_i2c_get_platformdata
- *
- * get the platform data associated with the given device, or return
- * the default if there is none
-*/
-
-static inline struct s3c2410_platform_i2c *s3c24xx_i2c_get_platformdata(struct device *dev)
-{
- if (dev->platform_data != NULL)
- return (struct s3c2410_platform_i2c *)dev->platform_data;
-
- return &s3c24xx_i2c_default_platform;
-}
-
/* s3c24xx_i2c_master_complete
*
* complete the message and wake up the caller, using the given return code,
@@ -130,7 +104,7 @@ static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret)
i2c->msg_ptr = 0;
i2c->msg = NULL;
- i2c->msg_idx ++;
+ i2c->msg_idx++;
i2c->msg_num = 0;
if (ret)
i2c->msg_idx = ret;
@@ -141,19 +115,17 @@ static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret)
static inline void s3c24xx_i2c_disable_ack(struct s3c24xx_i2c *i2c)
{
unsigned long tmp;
-
+
tmp = readl(i2c->regs + S3C2410_IICCON);
writel(tmp & ~S3C2410_IICCON_ACKEN, i2c->regs + S3C2410_IICCON);
-
}
static inline void s3c24xx_i2c_enable_ack(struct s3c24xx_i2c *i2c)
{
unsigned long tmp;
-
+
tmp = readl(i2c->regs + S3C2410_IICCON);
writel(tmp | S3C2410_IICCON_ACKEN, i2c->regs + S3C2410_IICCON);
-
}
/* irq enable/disable functions */
@@ -161,7 +133,7 @@ static inline void s3c24xx_i2c_enable_ack(struct s3c24xx_i2c *i2c)
static inline void s3c24xx_i2c_disable_irq(struct s3c24xx_i2c *i2c)
{
unsigned long tmp;
-
+
tmp = readl(i2c->regs + S3C2410_IICCON);
writel(tmp & ~S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON);
}
@@ -169,7 +141,7 @@ static inline void s3c24xx_i2c_disable_irq(struct s3c24xx_i2c *i2c)
static inline void s3c24xx_i2c_enable_irq(struct s3c24xx_i2c *i2c)
{
unsigned long tmp;
-
+
tmp = readl(i2c->regs + S3C2410_IICCON);
writel(tmp | S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON);
}
@@ -177,10 +149,10 @@ static inline void s3c24xx_i2c_enable_irq(struct s3c24xx_i2c *i2c)
/* s3c24xx_i2c_message_start
*
- * put the start of a message onto the bus
+ * put the start of a message onto the bus
*/
-static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
+static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
struct i2c_msg *msg)
{
unsigned int addr = (msg->addr & 0x7f) << 1;
@@ -199,15 +171,15 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
if (msg->flags & I2C_M_REV_DIR_ADDR)
addr ^= 1;
- // todo - check for wether ack wanted or not
+ /* todo - check for wether ack wanted or not */
s3c24xx_i2c_enable_ack(i2c);
iiccon = readl(i2c->regs + S3C2410_IICCON);
writel(stat, i2c->regs + S3C2410_IICSTAT);
-
+
dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr);
writeb(addr, i2c->regs + S3C2410_IICDS);
-
+
/* delay here to ensure the data byte has gotten onto the bus
* before the transaction is started */
@@ -215,8 +187,8 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon);
writel(iiccon, i2c->regs + S3C2410_IICCON);
-
- stat |= S3C2410_IICSTAT_START;
+
+ stat |= S3C2410_IICSTAT_START;
writel(stat, i2c->regs + S3C2410_IICSTAT);
}
@@ -227,11 +199,11 @@ static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
dev_dbg(i2c->dev, "STOP\n");
/* stop the transfer */
- iicstat &= ~ S3C2410_IICSTAT_START;
+ iicstat &= ~S3C2410_IICSTAT_START;
writel(iicstat, i2c->regs + S3C2410_IICSTAT);
-
+
i2c->state = STATE_STOP;
-
+
s3c24xx_i2c_master_complete(i2c, ret);
s3c24xx_i2c_disable_irq(i2c);
}
@@ -241,7 +213,7 @@ static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
/* is_lastmsg()
*
- * returns TRUE if the current message is the last in the set
+ * returns TRUE if the current message is the last in the set
*/
static inline int is_lastmsg(struct s3c24xx_i2c *i2c)
@@ -289,14 +261,14 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
case STATE_STOP:
dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__);
- s3c24xx_i2c_disable_irq(i2c);
+ s3c24xx_i2c_disable_irq(i2c);
goto out_ack;
case STATE_START:
/* last thing we did was send a start condition on the
* bus, or started a new i2c message
*/
-
+
if (iicstat & S3C2410_IICSTAT_LASTBIT &&
!(i2c->msg->flags & I2C_M_IGNORE_NAK)) {
/* ack was not received... */
@@ -322,7 +294,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
if (i2c->state == STATE_READ)
goto prepare_read;
- /* fall through to the write state, as we will need to
+ /* fall through to the write state, as we will need to
* send a byte as well */
case STATE_WRITE:
@@ -339,7 +311,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
}
}
- retry_write:
+ retry_write:
if (!is_msgend(i2c)) {
byte = i2c->msg->buf[i2c->msg_ptr++];
@@ -359,9 +331,9 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
dev_dbg(i2c->dev, "WRITE: Next Message\n");
i2c->msg_ptr = 0;
- i2c->msg_idx ++;
+ i2c->msg_idx++;
i2c->msg++;
-
+
/* check to see if we need to do another message */
if (i2c->msg->flags & I2C_M_NOSTART) {
@@ -375,7 +347,6 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
goto retry_write;
} else {
-
/* send the new start */
s3c24xx_i2c_message_start(i2c, i2c->msg);
i2c->state = STATE_START;
@@ -389,7 +360,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
break;
case STATE_READ:
- /* we have a byte of data in the data register, do
+ /* we have a byte of data in the data register, do
* something with it, and then work out wether we are
* going to do any more read/write
*/
@@ -397,13 +368,13 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
byte = readb(i2c->regs + S3C2410_IICDS);
i2c->msg->buf[i2c->msg_ptr++] = byte;
- prepare_read:
+ prepare_read:
if (is_msglast(i2c)) {
/* last byte of buffer */
if (is_lastmsg(i2c))
s3c24xx_i2c_disable_ack(i2c);
-
+
} else if (is_msgend(i2c)) {
/* ok, we've read the entire buffer, see if there
* is anything else we need to do */
@@ -429,7 +400,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
/* acknowlegde the IRQ and get back on with the work */
out_ack:
- tmp = readl(i2c->regs + S3C2410_IICCON);
+ tmp = readl(i2c->regs + S3C2410_IICCON);
tmp &= ~S3C2410_IICCON_IRQPEND;
writel(tmp, i2c->regs + S3C2410_IICCON);
out:
@@ -450,19 +421,19 @@ static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id)
status = readl(i2c->regs + S3C2410_IICSTAT);
if (status & S3C2410_IICSTAT_ARBITR) {
- // deal with arbitration loss
+ /* deal with arbitration loss */
dev_err(i2c->dev, "deal with arbitration loss\n");
}
if (i2c->state == STATE_IDLE) {
dev_dbg(i2c->dev, "IRQ: error i2c->state == IDLE\n");
- tmp = readl(i2c->regs + S3C2410_IICCON);
+ tmp = readl(i2c->regs + S3C2410_IICCON);
tmp &= ~S3C2410_IICCON_IRQPEND;
writel(tmp, i2c->regs + S3C2410_IICCON);
goto out;
}
-
+
/* pretty much this leaves us with the fact that we've
* transmitted or received whatever byte we last sent */
@@ -485,16 +456,13 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
while (timeout-- > 0) {
iicstat = readl(i2c->regs + S3C2410_IICSTAT);
-
+
if (!(iicstat & S3C2410_IICSTAT_BUSBUSY))
return 0;
msleep(1);
}
- dev_dbg(i2c->dev, "timeout: GPEDAT is %08x\n",
- __raw_readl(S3C2410_GPEDAT));
-
return -ETIMEDOUT;
}
@@ -503,7 +471,8 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
* this starts an i2c transfer
*/
-static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int num)
+static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
+ struct i2c_msg *msgs, int num)
{
unsigned long timeout;
int ret;
@@ -529,12 +498,12 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int
s3c24xx_i2c_enable_irq(i2c);
s3c24xx_i2c_message_start(i2c, msgs);
spin_unlock_irq(&i2c->lock);
-
+
timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
ret = i2c->msg_idx;
- /* having these next two as dev_err() makes life very
+ /* having these next two as dev_err() makes life very
* noisy when doing an i2cdetect */
if (timeout == 0)
@@ -591,19 +560,6 @@ static const struct i2c_algorithm s3c24xx_i2c_algorithm = {
.functionality = s3c24xx_i2c_func,
};
-static struct s3c24xx_i2c s3c24xx_i2c = {
- .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_i2c.lock),
- .wait = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait),
- .tx_setup = 50,
- .adap = {
- .name = "s3c2410-i2c",
- .owner = THIS_MODULE,
- .algo = &s3c24xx_i2c_algorithm,
- .retries = 2,
- .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
- },
-};
-
/* s3c24xx_i2c_calcdivisor
*
* return the divisor settings for a given frequency
@@ -643,7 +599,7 @@ static inline int freq_acceptable(unsigned int freq, unsigned int wanted)
{
int diff = freq - wanted;
- return (diff >= -2 && diff <= 2);
+ return diff >= -2 && diff <= 2;
}
/* s3c24xx_i2c_clockrate
@@ -655,7 +611,7 @@ static inline int freq_acceptable(unsigned int freq, unsigned int wanted)
static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
{
- struct s3c2410_platform_i2c *pdata;
+ struct s3c2410_platform_i2c *pdata = i2c->dev->platform_data;
unsigned long clkin = clk_get_rate(i2c->clk);
unsigned int divs, div1;
u32 iiccon;
@@ -663,10 +619,8 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
int start, end;
i2c->clkrate = clkin;
-
- pdata = s3c24xx_i2c_get_platformdata(i2c->adap.dev.parent);
clkin /= 1000; /* clkin now in KHz */
-
+
dev_dbg(i2c->dev, "pdata %p, freq %lu %lu..%lu\n",
pdata, pdata->bus_freq, pdata->min_freq, pdata->max_freq);
@@ -774,7 +728,7 @@ static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c)
/* s3c24xx_i2c_init
*
- * initialise the controller, set the IO lines and frequency
+ * initialise the controller, set the IO lines and frequency
*/
static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
@@ -785,15 +739,15 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
/* get the plafrom data */
- pdata = s3c24xx_i2c_get_platformdata(i2c->adap.dev.parent);
+ pdata = i2c->dev->platform_data;
/* inititalise the gpio */
- s3c2410_gpio_cfgpin(S3C2410_GPE15, S3C2410_GPE15_IICSDA);
- s3c2410_gpio_cfgpin(S3C2410_GPE14, S3C2410_GPE14_IICSCL);
+ if (pdata->cfg_gpio)
+ pdata->cfg_gpio(to_platform_device(i2c->dev));
/* write slave address */
-
+
writeb(pdata->slave_addr, i2c->regs + S3C2410_IICADD);
dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr);
@@ -831,12 +785,32 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
static int s3c24xx_i2c_probe(struct platform_device *pdev)
{
- struct s3c24xx_i2c *i2c = &s3c24xx_i2c;
+ struct s3c24xx_i2c *i2c;
struct s3c2410_platform_i2c *pdata;
struct resource *res;
int ret;
- pdata = s3c24xx_i2c_get_platformdata(&pdev->dev);
+ pdata = pdev->dev.platform_data;
+ if (!pdata) {
+ dev_err(&pdev->dev, "no platform data\n");
+ return -EINVAL;
+ }
+
+ i2c = kzalloc(sizeof(struct s3c24xx_i2c), GFP_KERNEL);
+ if (!i2c) {
+ dev_err(&pdev->dev, "no memory for state\n");
+ return -ENOMEM;
+ }
+
+ strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name));
+ i2c->adap.owner = THIS_MODULE;
+ i2c->adap.algo = &s3c24xx_i2c_algorithm;
+ i2c->adap.retries = 2;
+ i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
+ i2c->tx_setup = 50;
+
+ spin_lock_init(&i2c->lock);
+ init_waitqueue_head(&i2c->wait);
/* find the clock and enable it */
@@ -878,7 +852,8 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
goto err_ioarea;
}
- dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", i2c->regs, i2c->ioarea, res);
+ dev_dbg(&pdev->dev, "registers %p (%p, %p)\n",
+ i2c->regs, i2c->ioarea, res);
/* setup info block for the i2c core */
@@ -892,29 +867,23 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
goto err_iomap;
/* find the IRQ for this unit (note, this relies on the init call to
- * ensure no current IRQs pending
+ * ensure no current IRQs pending
*/
- res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (res == NULL) {
+ i2c->irq = ret = platform_get_irq(pdev, 0);
+ if (ret <= 0) {
dev_err(&pdev->dev, "cannot find IRQ\n");
- ret = -ENOENT;
goto err_iomap;
}
- ret = request_irq(res->start, s3c24xx_i2c_irq, IRQF_DISABLED,
- pdev->name, i2c);
+ ret = request_irq(i2c->irq, s3c24xx_i2c_irq, IRQF_DISABLED,
+ dev_name(&pdev->dev), i2c);
if (ret != 0) {
- dev_err(&pdev->dev, "cannot claim IRQ\n");
+ dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
goto err_iomap;
}
- i2c->irq = res;
-
- dev_dbg(&pdev->dev, "irq resource %p (%lu)\n", res,
- (unsigned long)res->start);
-
ret = s3c24xx_i2c_register_cpufreq(i2c);
if (ret < 0) {
dev_err(&pdev->dev, "failed to register cpufreq notifier\n");
@@ -944,7 +913,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
s3c24xx_i2c_deregister_cpufreq(i2c);
err_irq:
- free_irq(i2c->irq->start, i2c);
+ free_irq(i2c->irq, i2c);
err_iomap:
iounmap(i2c->regs);
@@ -958,6 +927,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
clk_put(i2c->clk);
err_noclk:
+ kfree(i2c);
return ret;
}
@@ -973,7 +943,7 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
s3c24xx_i2c_deregister_cpufreq(i2c);
i2c_del_adapter(&i2c->adap);
- free_irq(i2c->irq->start, i2c);
+ free_irq(i2c->irq, i2c);
clk_disable(i2c->clk);
clk_put(i2c->clk);
@@ -982,6 +952,7 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
release_resource(i2c->ioarea);
kfree(i2c->ioarea);
+ kfree(i2c);
return 0;
}
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 4c35702830c..864ac561fdb 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -126,19 +126,6 @@ config ISP1301_OMAP
This driver can also be built as a module. If so, the module
will be called isp1301_omap.
-config TPS65010
- tristate "TPS6501x Power Management chips"
- depends on GPIOLIB
- default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
- help
- If you say yes here you get support for the TPS6501x series of
- Power Management chips. These include voltage regulators,
- lithium ion/polymer battery charging, and other features that
- are often used in portable devices like cell phones and cameras.
-
- This driver can also be built as a module. If so, the module
- will be called tps65010.
-
config SENSORS_MAX6875
tristate "Maxim MAX6875 Power supply supervisor"
depends on EXPERIMENTAL
@@ -164,16 +151,6 @@ config SENSORS_TSL2550
This driver can also be built as a module. If so, the module
will be called tsl2550.
-config MENELAUS
- bool "TWL92330/Menelaus PM chip"
- depends on I2C=y && ARCH_OMAP24XX
- help
- If you say yes here you get support for the Texas Instruments
- TWL92330/Menelaus Power Management chip. This include voltage
- regulators, Dual slot memory card tranceivers, real-time clock
- and other features that are often used in portable devices like
- cell phones and PDAs.
-
config MCU_MPC8349EMITX
tristate "MPC8349E-mITX MCU driver"
depends on I2C && PPC_83xx
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 23d2a31b0a6..8b95f41a500 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -19,8 +19,6 @@ obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
obj-$(CONFIG_PCF8575) += pcf8575.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
-obj-$(CONFIG_TPS65010) += tps65010.o
-obj-$(CONFIG_MENELAUS) += menelaus.o
obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o
obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
index 53912c327bf..8dc2bb78160 100644
--- a/drivers/infiniband/hw/ipath/ipath_fs.c
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -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) {
diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
index d5b4cc357a3..650120261ab 100644
--- a/drivers/isdn/capi/capidrv.c
+++ b/drivers/isdn/capi/capidrv.c
@@ -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++)
diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c
index 0aa66ec4cbd..b129409925a 100644
--- a/drivers/isdn/capi/capifs.c
+++ b/drivers/isdn/capi/capifs.c
@@ -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;
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index 1c615804ea7..72880b7e28d 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -3,9 +3,10 @@
#
dm-mod-objs := dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \
- dm-ioctl.o dm-io.o dm-kcopyd.o
+ dm-ioctl.o dm-io.o dm-kcopyd.o dm-sysfs.o
dm-multipath-objs := dm-path-selector.o dm-mpath.o
-dm-snapshot-objs := dm-snap.o dm-exception-store.o
+dm-snapshot-objs := dm-snap.o dm-exception-store.o dm-snap-transient.o \
+ dm-snap-persistent.o
dm-mirror-objs := dm-raid1.o
md-mod-objs := md.o bitmap.o
raid456-objs := raid5.o raid6algos.o raid6recov.o raid6tables.o \
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 3326750ec02..35bda49796f 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -1322,11 +1322,7 @@ static int __init dm_crypt_init(void)
static void __exit dm_crypt_exit(void)
{
- int r = dm_unregister_target(&crypt_target);
-
- if (r < 0)
- DMERR("unregister failed %d", r);
-
+ dm_unregister_target(&crypt_target);
kmem_cache_destroy(_crypt_io_pool);
}
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c
index 848b381f117..59ee1b015d2 100644
--- a/drivers/md/dm-delay.c
+++ b/drivers/md/dm-delay.c
@@ -364,11 +364,7 @@ bad_queue:
static void __exit dm_delay_exit(void)
{
- int r = dm_unregister_target(&delay_target);
-
- if (r < 0)
- DMERR("unregister failed %d", r);
-
+ dm_unregister_target(&delay_target);
kmem_cache_destroy(delayed_cache);
destroy_workqueue(kdelayd_wq);
}
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
index 01590f3e000..dccbfb0e010 100644
--- a/drivers/md/dm-exception-store.c
+++ b/drivers/md/dm-exception-store.c
@@ -1,756 +1,45 @@
/*
- * dm-exception-store.c
- *
* Copyright (C) 2001-2002 Sistina Software (UK) Limited.
- * Copyright (C) 2006 Red Hat GmbH
+ * Copyright (C) 2006-2008 Red Hat GmbH
*
* This file is released under the GPL.
*/
-#include "dm-snap.h"
+#include "dm-exception-store.h"
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
-#include <linux/dm-io.h>
-#include <linux/dm-kcopyd.h>
-
-#define DM_MSG_PREFIX "snapshots"
-#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */
-
-/*-----------------------------------------------------------------
- * Persistent snapshots, by persistent we mean that the snapshot
- * will survive a reboot.
- *---------------------------------------------------------------*/
-
-/*
- * We need to store a record of which parts of the origin have
- * been copied to the snapshot device. The snapshot code
- * requires that we copy exception chunks to chunk aligned areas
- * of the COW store. It makes sense therefore, to store the
- * metadata in chunk size blocks.
- *
- * There is no backward or forward compatibility implemented,
- * snapshots with different disk versions than the kernel will
- * not be usable. It is expected that "lvcreate" will blank out
- * the start of a fresh COW device before calling the snapshot
- * constructor.
- *
- * The first chunk of the COW device just contains the header.
- * After this there is a chunk filled with exception metadata,
- * followed by as many exception chunks as can fit in the
- * metadata areas.
- *
- * All on disk structures are in little-endian format. The end
- * of the exceptions info is indicated by an exception with a
- * new_chunk of 0, which is invalid since it would point to the
- * header chunk.
- */
-
-/*
- * Magic for persistent snapshots: "SnAp" - Feeble isn't it.
- */
-#define SNAP_MAGIC 0x70416e53
-
-/*
- * The on-disk version of the metadata.
- */
-#define SNAPSHOT_DISK_VERSION 1
-
-struct disk_header {
- uint32_t magic;
-
- /*
- * Is this snapshot valid. There is no way of recovering
- * an invalid snapshot.
- */
- uint32_t valid;
-
- /*
- * Simple, incrementing version. no backward
- * compatibility.
- */
- uint32_t version;
-
- /* In sectors */
- uint32_t chunk_size;
-};
-
-struct disk_exception {
- uint64_t old_chunk;
- uint64_t new_chunk;
-};
-
-struct commit_callback {
- void (*callback)(void *, int success);
- void *context;
-};
-
-/*
- * The top level structure for a persistent exception store.
- */
-struct pstore {
- struct dm_snapshot *snap; /* up pointer to my snapshot */
- int version;
- int valid;
- uint32_t exceptions_per_area;
-
- /*
- * Now that we have an asynchronous kcopyd there is no
- * need for large chunk sizes, so it wont hurt to have a
- * whole chunks worth of metadata in memory at once.
- */
- void *area;
-
- /*
- * An area of zeros used to clear the next area.
- */
- void *zero_area;
-
- /*
- * Used to keep track of which metadata area the data in
- * 'chunk' refers to.
- */
- chunk_t current_area;
-
- /*
- * The next free chunk for an exception.
- */
- chunk_t next_free;
-
- /*
- * The index of next free exception in the current
- * metadata area.
- */
- uint32_t current_committed;
-
- atomic_t pending_count;
- uint32_t callback_count;
- struct commit_callback *callbacks;
- struct dm_io_client *io_client;
-
- struct workqueue_struct *metadata_wq;
-};
-
-static unsigned sectors_to_pages(unsigned sectors)
-{
- return DIV_ROUND_UP(sectors, PAGE_SIZE >> 9);
-}
-
-static int alloc_area(struct pstore *ps)
-{
- int r = -ENOMEM;
- size_t len;
-
- len = ps->snap->chunk_size << SECTOR_SHIFT;
-
- /*
- * Allocate the chunk_size block of memory that will hold
- * a single metadata area.
- */
- ps->area = vmalloc(len);
- if (!ps->area)
- return r;
-
- ps->zero_area = vmalloc(len);
- if (!ps->zero_area) {
- vfree(ps->area);
- return r;
- }
- memset(ps->zero_area, 0, len);
-
- return 0;
-}
-
-static void free_area(struct pstore *ps)
-{
- vfree(ps->area);
- ps->area = NULL;
- vfree(ps->zero_area);
- ps->zero_area = NULL;
-}
-
-struct mdata_req {
- struct dm_io_region *where;
- struct dm_io_request *io_req;
- struct work_struct work;
- int result;
-};
-
-static void do_metadata(struct work_struct *work)
-{
- struct mdata_req *req = container_of(work, struct mdata_req, work);
-
- req->result = dm_io(req->io_req, 1, req->where, NULL);
-}
-
-/*
- * Read or write a chunk aligned and sized block of data from a device.
- */
-static int chunk_io(struct pstore *ps, chunk_t chunk, int rw, int metadata)
-{
- struct dm_io_region where = {
- .bdev = ps->snap->cow->bdev,
- .sector = ps->snap->chunk_size * chunk,
- .count = ps->snap->chunk_size,
- };
- struct dm_io_request io_req = {
- .bi_rw = rw,
- .mem.type = DM_IO_VMA,
- .mem.ptr.vma = ps->area,
- .client = ps->io_client,
- .notify.fn = NULL,
- };
- struct mdata_req req;
-
- if (!metadata)
- return dm_io(&io_req, 1, &where, NULL);
-
- req.where = &where;
- req.io_req = &io_req;
-
- /*
- * Issue the synchronous I/O from a different thread
- * to avoid generic_make_request recursion.
- */
- INIT_WORK(&req.work, do_metadata);
- queue_work(ps->metadata_wq, &req.work);
- flush_workqueue(ps->metadata_wq);
-
- return req.result;
-}
-
-/*
- * Convert a metadata area index to a chunk index.
- */
-static chunk_t area_location(struct pstore *ps, chunk_t area)
-{
- return 1 + ((ps->exceptions_per_area + 1) * area);
-}
-
-/*
- * Read or write a metadata area. Remembering to skip the first
- * chunk which holds the header.
- */
-static int area_io(struct pstore *ps, int rw)
-{
- int r;
- chunk_t chunk;
-
- chunk = area_location(ps, ps->current_area);
-
- r = chunk_io(ps, chunk, rw, 0);
- if (r)
- return r;
-
- return 0;
-}
-
-static void zero_memory_area(struct pstore *ps)
-{
- memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
-}
-
-static int zero_disk_area(struct pstore *ps, chunk_t area)
-{
- struct dm_io_region where = {
- .bdev = ps->snap->cow->bdev,
- .sector = ps->snap->chunk_size * area_location(ps, area),
- .count = ps->snap->chunk_size,
- };
- struct dm_io_request io_req = {
- .bi_rw = WRITE,
- .mem.type = DM_IO_VMA,
- .mem.ptr.vma = ps->zero_area,
- .client = ps->io_client,
- .notify.fn = NULL,
- };
-
- return dm_io(&io_req, 1, &where, NULL);
-}
-
-static int read_header(struct pstore *ps, int *new_snapshot)
-{
- int r;
- struct disk_header *dh;
- chunk_t chunk_size;
- int chunk_size_supplied = 1;
-
- /*
- * Use default chunk size (or hardsect_size, if larger) if none supplied
- */
- if (!ps->snap->chunk_size) {
- ps->snap->chunk_size = max(DM_CHUNK_SIZE_DEFAULT_SECTORS,
- bdev_hardsect_size(ps->snap->cow->bdev) >> 9);
- ps->snap->chunk_mask = ps->snap->chunk_size - 1;
- ps->snap->chunk_shift = ffs(ps->snap->chunk_size) - 1;
- chunk_size_supplied = 0;
- }
-
- ps->io_client = dm_io_client_create(sectors_to_pages(ps->snap->
- chunk_size));
- if (IS_ERR(ps->io_client))
- return PTR_ERR(ps->io_client);
-
- r = alloc_area(ps);
- if (r)
- return r;
-
- r = chunk_io(ps, 0, READ, 1);
- if (r)
- goto bad;
-
- dh = (struct disk_header *) ps->area;
-
- if (le32_to_cpu(dh->magic) == 0) {
- *new_snapshot = 1;
- return 0;
- }
-
- if (le32_to_cpu(dh->magic) != SNAP_MAGIC) {
- DMWARN("Invalid or corrupt snapshot");
- r = -ENXIO;
- goto bad;
- }
-
- *new_snapshot = 0;
- ps->valid = le32_to_cpu(dh->valid);
- ps->version = le32_to_cpu(dh->version);
- chunk_size = le32_to_cpu(dh->chunk_size);
-
- if (!chunk_size_supplied || ps->snap->chunk_size == chunk_size)
- return 0;
-
- DMWARN("chunk size %llu in device metadata overrides "
- "table chunk size of %llu.",
- (unsigned long long)chunk_size,
- (unsigned long long)ps->snap->chunk_size);
-
- /* We had a bogus chunk_size. Fix stuff up. */
- free_area(ps);
-
- ps->snap->chunk_size = chunk_size;
- ps->snap->chunk_mask = chunk_size - 1;
- ps->snap->chunk_shift = ffs(chunk_size) - 1;
-
- r = dm_io_client_resize(sectors_to_pages(ps->snap->chunk_size),
- ps->io_client);
- if (r)
- return r;
-
- r = alloc_area(ps);
- return r;
-
-bad:
- free_area(ps);
- return r;
-}
-
-static int write_header(struct pstore *ps)
-{
- struct disk_header *dh;
-
- memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
-
- dh = (struct disk_header *) ps->area;
- dh->magic = cpu_to_le32(SNAP_MAGIC);
- dh->valid = cpu_to_le32(ps->valid);
- dh->version = cpu_to_le32(ps->version);
- dh->chunk_size = cpu_to_le32(ps->snap->chunk_size);
-
- return chunk_io(ps, 0, WRITE, 1);
-}
-
-/*
- * Access functions for the disk exceptions, these do the endian conversions.
- */
-static struct disk_exception *get_exception(struct pstore *ps, uint32_t index)
-{
- BUG_ON(index >= ps->exceptions_per_area);
-
- return ((struct disk_exception *) ps->area) + index;
-}
-static void read_exception(struct pstore *ps,
- uint32_t index, struct disk_exception *result)
-{
- struct disk_exception *e = get_exception(ps, index);
-
- /* copy it */
- result->old_chunk = le64_to_cpu(e->old_chunk);
- result->new_chunk = le64_to_cpu(e->new_chunk);
-}
-
-static void write_exception(struct pstore *ps,
- uint32_t index, struct disk_exception *de)
-{
- struct disk_exception *e = get_exception(ps, index);
-
- /* copy it */
- e->old_chunk = cpu_to_le64(de->old_chunk);
- e->new_chunk = cpu_to_le64(de->new_chunk);
-}
+#define DM_MSG_PREFIX "snapshot exception stores"
-/*
- * Registers the exceptions that are present in the current area.
- * 'full' is filled in to indicate if the area has been
- * filled.
- */
-static int insert_exceptions(struct pstore *ps, int *full)
+int dm_exception_store_init(void)
{
int r;
- unsigned int i;
- struct disk_exception de;
-
- /* presume the area is full */
- *full = 1;
-
- for (i = 0; i < ps->exceptions_per_area; i++) {
- read_exception(ps, i, &de);
-
- /*
- * If the new_chunk is pointing at the start of
- * the COW device, where the first metadata area
- * is we know that we've hit the end of the
- * exceptions. Therefore the area is not full.
- */
- if (de.new_chunk == 0LL) {
- ps->current_committed = i;
- *full = 0;
- break;
- }
-
- /*
- * Keep track of the start of the free chunks.
- */
- if (ps->next_free <= de.new_chunk)
- ps->next_free = de.new_chunk + 1;
-
- /*
- * Otherwise we add the exception to the snapshot.
- */
- r = dm_add_exception(ps->snap, de.old_chunk, de.new_chunk);
- if (r)
- return r;
- }
-
- return 0;
-}
-
-static int read_exceptions(struct pstore *ps)
-{
- int r, full = 1;
-
- /*
- * Keeping reading chunks and inserting exceptions until
- * we find a partially full area.
- */
- for (ps->current_area = 0; full; ps->current_area++) {
- r = area_io(ps, READ);
- if (r)
- return r;
- r = insert_exceptions(ps, &full);
- if (r)
- return r;
+ r = dm_transient_snapshot_init();
+ if (r) {
+ DMERR("Unable to register transient exception store type.");
+ goto transient_fail;
}
- ps->current_area--;
-
- return 0;
-}
-
-static struct pstore *get_info(struct exception_store *store)
-{
- return (struct pstore *) store->context;
-}
-
-static void persistent_fraction_full(struct exception_store *store,
- sector_t *numerator, sector_t *denominator)
-{
- *numerator = get_info(store)->next_free * store->snap->chunk_size;
- *denominator = get_dev_size(store->snap->cow->bdev);
-}
-
-static void persistent_destroy(struct exception_store *store)
-{
- struct pstore *ps = get_info(store);
-
- destroy_workqueue(ps->metadata_wq);
- dm_io_client_destroy(ps->io_client);
- vfree(ps->callbacks);
- free_area(ps);
- kfree(ps);
-}
-
-static int persistent_read_metadata(struct exception_store *store)
-{
- int r, uninitialized_var(new_snapshot);
- struct pstore *ps = get_info(store);
-
- /*
- * Read the snapshot header.
- */
- r = read_header(ps, &new_snapshot);
- if (r)
- return r;
-
- /*
- * Now we know correct chunk_size, complete the initialisation.
- */
- ps->exceptions_per_area = (ps->snap->chunk_size << SECTOR_SHIFT) /
- sizeof(struct disk_exception);
- ps->callbacks = dm_vcalloc(ps->exceptions_per_area,
- sizeof(*ps->callbacks));
- if (!ps->callbacks)
- return -ENOMEM;
-
- /*
- * Do we need to setup a new snapshot ?
- */
- if (new_snapshot) {
- r = write_header(ps);
- if (r) {
- DMWARN("write_header failed");
- return r;
- }
-
- ps->current_area = 0;
- zero_memory_area(ps);
- r = zero_disk_area(ps, 0);
- if (r) {
- DMWARN("zero_disk_area(0) failed");
- return r;
- }
- } else {
- /*
- * Sanity checks.
- */
- if (ps->version != SNAPSHOT_DISK_VERSION) {
- DMWARN("unable to handle snapshot disk version %d",
- ps->version);
- return -EINVAL;
- }
-
- /*
- * Metadata are valid, but snapshot is invalidated
- */
- if (!ps->valid)
- return 1;
-
- /*
- * Read the metadata.
- */
- r = read_exceptions(ps);
- if (r)
- return r;
+ r = dm_persistent_snapshot_init();
+ if (r) {
+ DMERR("Unable to register persistent exception store type");
+ goto persistent_fail;
}
return 0;
-}
-
-static int persistent_prepare(struct exception_store *store,
- struct dm_snap_exception *e)
-{
- struct pstore *ps = get_info(store);
- uint32_t stride;
- chunk_t next_free;
- sector_t size = get_dev_size(store->snap->cow->bdev);
-
- /* Is there enough room ? */
- if (size < ((ps->next_free + 1) * store->snap->chunk_size))
- return -ENOSPC;
- e->new_chunk = ps->next_free;
-
- /*
- * Move onto the next free pending, making sure to take
- * into account the location of the metadata chunks.
- */
- stride = (ps->exceptions_per_area + 1);
- next_free = ++ps->next_free;
- if (sector_div(next_free, stride) == 1)
- ps->next_free++;
-
- atomic_inc(&ps->pending_count);
- return 0;
-}
-
-static void persistent_commit(struct exception_store *store,
- struct dm_snap_exception *e,
- void (*callback) (void *, int success),
- void *callback_context)
-{
- unsigned int i;
- struct pstore *ps = get_info(store);
- struct disk_exception de;
- struct commit_callback *cb;
-
- de.old_chunk = e->old_chunk;
- de.new_chunk = e->new_chunk;
- write_exception(ps, ps->current_committed++, &de);
-
- /*
- * Add the callback to the back of the array. This code
- * is the only place where the callback array is
- * manipulated, and we know that it will never be called
- * multiple times concurrently.
- */
- cb = ps->callbacks + ps->callback_count++;
- cb->callback = callback;
- cb->context = callback_context;
-
- /*
- * If there are exceptions in flight and we have not yet
- * filled this metadata area there's nothing more to do.
- */
- if (!atomic_dec_and_test(&ps->pending_count) &&
- (ps->current_committed != ps->exceptions_per_area))
- return;
-
- /*
- * If we completely filled the current area, then wipe the next one.
- */
- if ((ps->current_committed == ps->exceptions_per_area) &&
- zero_disk_area(ps, ps->current_area + 1))
- ps->valid = 0;
-
- /*
- * Commit exceptions to disk.
- */
- if (ps->valid && area_io(ps, WRITE))
- ps->valid = 0;
-
- /*
- * Advance to the next area if this one is full.
- */
- if (ps->current_committed == ps->exceptions_per_area) {
- ps->current_committed = 0;
- ps->current_area++;
- zero_memory_area(ps);
- }
-
- for (i = 0; i < ps->callback_count; i++) {
- cb = ps->callbacks + i;
- cb->callback(cb->context, ps->valid);
- }
-
- ps->callback_count = 0;
-}
-
-static void persistent_drop(struct exception_store *store)
-{
- struct pstore *ps = get_info(store);
-
- ps->valid = 0;
- if (write_header(ps))
- DMWARN("write header failed");
-}
-
-int dm_create_persistent(struct exception_store *store)
-{
- struct pstore *ps;
-
- /* allocate the pstore */
- ps = kmalloc(sizeof(*ps), GFP_KERNEL);
- if (!ps)
- return -ENOMEM;
-
- ps->snap = store->snap;
- ps->valid = 1;
- ps->version = SNAPSHOT_DISK_VERSION;
- ps->area = NULL;
- ps->next_free = 2; /* skipping the header and first area */
- ps->current_committed = 0;
-
- ps->callback_count = 0;
- atomic_set(&ps->pending_count, 0);
- ps->callbacks = NULL;
-
- ps->metadata_wq = create_singlethread_workqueue("ksnaphd");
- if (!ps->metadata_wq) {
- kfree(ps);
- DMERR("couldn't start header metadata update thread");
- return -ENOMEM;
- }
-
- store->destroy = persistent_destroy;
- store->read_metadata = persistent_read_metadata;
- store->prepare_exception = persistent_prepare;
- store->commit_exception = persistent_commit;
- store->drop_snapshot = persistent_drop;
- store->fraction_full = persistent_fraction_full;
- store->context = ps;
-
- return 0;
-}
-
-/*-----------------------------------------------------------------
- * Implementation of the store for non-persistent snapshots.
- *---------------------------------------------------------------*/
-struct transient_c {
- sector_t next_free;
-};
-
-static void transient_destroy(struct exception_store *store)
-{
- kfree(store->context);
-}
-
-static int transient_read_metadata(struct exception_store *store)
-{
- return 0;
-}
-
-static int transient_prepare(struct exception_store *store,
- struct dm_snap_exception *e)
-{
- struct transient_c *tc = (struct transient_c *) store->context;
- sector_t size = get_dev_size(store->snap->cow->bdev);
-
- if (size < (tc->next_free + store->snap->chunk_size))
- return -1;
-
- e->new_chunk = sector_to_chunk(store->snap, tc->next_free);
- tc->next_free += store->snap->chunk_size;
-
- return 0;
-}
-
-static void transient_commit(struct exception_store *store,
- struct dm_snap_exception *e,
- void (*callback) (void *, int success),
- void *callback_context)
-{
- /* Just succeed */
- callback(callback_context, 1);
-}
-
-static void transient_fraction_full(struct exception_store *store,
- sector_t *numerator, sector_t *denominator)
-{
- *numerator = ((struct transient_c *) store->context)->next_free;
- *denominator = get_dev_size(store->snap->cow->bdev);
+persistent_fail:
+ dm_persistent_snapshot_exit();
+transient_fail:
+ return r;
}
-int dm_create_transient(struct exception_store *store)
+void dm_exception_store_exit(void)
{
- struct transient_c *tc;
-
- store->destroy = transient_destroy;
- store->read_metadata = transient_read_metadata;
- store->prepare_exception = transient_prepare;
- store->commit_exception = transient_commit;
- store->drop_snapshot = NULL;
- store->fraction_full = transient_fraction_full;
-
- tc = kmalloc(sizeof(struct transient_c), GFP_KERNEL);
- if (!tc)
- return -ENOMEM;
-
- tc->next_free = 0;
- store->context = tc;
-
- return 0;
+ dm_persistent_snapshot_exit();
+ dm_transient_snapshot_exit();
}
diff --git a/drivers/md/dm-exception-store.h b/drivers/md/dm-exception-store.h
new file mode 100644
index 00000000000..bb9f33d5daa
--- /dev/null
+++ b/drivers/md/dm-exception-store.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
+ * Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+ *
+ * Device-mapper snapshot exception store.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LINUX_DM_EXCEPTION_STORE
+#define _LINUX_DM_EXCEPTION_STORE
+
+#include <linux/blkdev.h>
+#include <linux/device-mapper.h>
+
+/*
+ * The snapshot code deals with largish chunks of the disk at a
+ * time. Typically 32k - 512k.
+ */
+typedef sector_t chunk_t;
+
+/*
+ * An exception is used where an old chunk of data has been
+ * replaced by a new one.
+ * If chunk_t is 64 bits in size, the top 8 bits of new_chunk hold the number
+ * of chunks that follow contiguously. Remaining bits hold the number of the
+ * chunk within the device.
+ */
+struct dm_snap_exception {
+ struct list_head hash_list;
+
+ chunk_t old_chunk;
+ chunk_t new_chunk;
+};
+
+/*
+ * Abstraction to handle the meta/layout of exception stores (the
+ * COW device).
+ */
+struct dm_exception_store {
+ /*
+ * Destroys this object when you've finished with it.
+ */
+ void (*destroy) (struct dm_exception_store *store);
+
+ /*
+ * The target shouldn't read the COW device until this is
+ * called. As exceptions are read from the COW, they are
+ * reported back via the callback.
+ */
+ int (*read_metadata) (struct dm_exception_store *store,
+ int (*callback)(void *callback_context,
+ chunk_t old, chunk_t new),
+ void *callback_context);
+
+ /*
+ * Find somewhere to store the next exception.
+ */
+ int (*prepare_exception) (struct dm_exception_store *store,
+ struct dm_snap_exception *e);
+
+ /*
+ * Update the metadata with this exception.
+ */
+ void (*commit_exception) (struct dm_exception_store *store,
+ struct dm_snap_exception *e,
+ void (*callback) (void *, int success),
+ void *callback_context);
+
+ /*
+ * The snapshot is invalid, note this in the metadata.
+ */
+ void (*drop_snapshot) (struct dm_exception_store *store);
+
+ int (*status) (struct dm_exception_store *store, status_type_t status,
+ char *result, unsigned int maxlen);
+
+ /*
+ * Return how full the snapshot is.
+ */
+ void (*fraction_full) (struct dm_exception_store *store,
+ sector_t *numerator,
+ sector_t *denominator);
+
+ struct dm_snapshot *snap;
+ void *context;
+};
+
+/*
+ * Funtions to manipulate consecutive chunks
+ */
+# if defined(CONFIG_LBD) || (BITS_PER_LONG == 64)
+# define DM_CHUNK_CONSECUTIVE_BITS 8
+# define DM_CHUNK_NUMBER_BITS 56
+
+static inline chunk_t dm_chunk_number(chunk_t chunk)
+{
+ return chunk & (chunk_t)((1ULL << DM_CHUNK_NUMBER_BITS) - 1ULL);
+}
+
+static inline unsigned dm_consecutive_chunk_count(struct dm_snap_exception *e)
+{
+ return e->new_chunk >> DM_CHUNK_NUMBER_BITS;
+}
+
+static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e)
+{
+ e->new_chunk += (1ULL << DM_CHUNK_NUMBER_BITS);
+
+ BUG_ON(!dm_consecutive_chunk_count(e));
+}
+
+# else
+# define DM_CHUNK_CONSECUTIVE_BITS 0
+
+static inline chunk_t dm_chunk_number(chunk_t chunk)
+{
+ return chunk;
+}
+
+static inline unsigned dm_consecutive_chunk_count(struct dm_snap_exception *e)
+{
+ return 0;
+}
+
+static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e)
+{
+}
+
+# endif
+
+int dm_exception_store_init(void);
+void dm_exception_store_exit(void);
+
+/*
+ * Two exception store implementations.
+ */
+int dm_persistent_snapshot_init(void);
+void dm_persistent_snapshot_exit(void);
+
+int dm_transient_snapshot_init(void);
+void dm_transient_snapshot_exit(void);
+
+int dm_create_persistent(struct dm_exception_store *store);
+
+int dm_create_transient(struct dm_exception_store *store);
+
+#endif /* _LINUX_DM_EXCEPTION_STORE */
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 777c948180f..54d0588fc1f 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -233,7 +233,7 @@ static void __hash_remove(struct hash_cell *hc)
}
if (hc->new_map)
- dm_table_put(hc->new_map);
+ dm_table_destroy(hc->new_map);
dm_put(hc->md);
free_cell(hc);
}
@@ -827,8 +827,8 @@ static int do_resume(struct dm_ioctl *param)
r = dm_swap_table(md, new_map);
if (r) {
+ dm_table_destroy(new_map);
dm_put(md);
- dm_table_put(new_map);
return r;
}
@@ -836,8 +836,6 @@ static int do_resume(struct dm_ioctl *param)
set_disk_ro(dm_disk(md), 0);
else
set_disk_ro(dm_disk(md), 1);
-
- dm_table_put(new_map);
}
if (dm_suspended(md))
@@ -1080,7 +1078,7 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
}
if (hc->new_map)
- dm_table_put(hc->new_map);
+ dm_table_destroy(hc->new_map);
hc->new_map = t;
up_write(&_hash_lock);
@@ -1109,7 +1107,7 @@ static int table_clear(struct dm_ioctl *param, size_t param_size)
}
if (hc->new_map) {
- dm_table_put(hc->new_map);
+ dm_table_destroy(hc->new_map);
hc->new_map = NULL;
}
@@ -1550,8 +1548,10 @@ int dm_copy_name_and_uuid(struct mapped_device *md, char *name, char *uuid)
goto out;
}
- strcpy(name, hc->name);
- strcpy(uuid, hc->uuid ? : "");
+ if (name)
+ strcpy(name, hc->name);
+ if (uuid)
+ strcpy(uuid, hc->uuid ? : "");
out:
up_read(&_hash_lock);
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 44042becad8..bfa107f59d9 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -142,6 +142,7 @@ static struct target_type linear_target = {
.status = linear_status,
.ioctl = linear_ioctl,
.merge = linear_merge,
+ .features = DM_TARGET_SUPPORTS_BARRIERS,
};
int __init dm_linear_init(void)
@@ -156,8 +157,5 @@ int __init dm_linear_init(void)
void dm_linear_exit(void)
{
- int r = dm_unregister_target(&linear_target);
-
- if (r < 0)
- DMERR("unregister failed %d", r);
+ dm_unregister_target(&linear_target);
}
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index a8c0fc79ca7..737961f275c 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -326,8 +326,6 @@ static void header_from_disk(struct log_header *core, struct log_header *disk)
static int rw_header(struct log_c *lc, int rw)
{
lc->io_req.bi_rw = rw;
- lc->io_req.mem.ptr.vma = lc->disk_header;
- lc->io_req.notify.fn = NULL;
return dm_io(&lc->io_req, 1, &lc->header_location, NULL);
}
@@ -362,10 +360,15 @@ static int read_header(struct log_c *log)
return 0;
}
-static inline int write_header(struct log_c *log)
+static int _check_region_size(struct dm_target *ti, uint32_t region_size)
{
- header_to_disk(&log->header, log->disk_header);
- return rw_header(log, WRITE);
+ if (region_size < 2 || region_size > ti->len)
+ return 0;
+
+ if (!is_power_of_2(region_size))
+ return 0;
+
+ return 1;
}
/*----------------------------------------------------------------
@@ -403,8 +406,9 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
}
}
- if (sscanf(argv[0], "%u", &region_size) != 1) {
- DMWARN("invalid region size string");
+ if (sscanf(argv[0], "%u", &region_size) != 1 ||
+ !_check_region_size(ti, region_size)) {
+ DMWARN("invalid region size %s", argv[0]);
return -EINVAL;
}
@@ -453,8 +457,18 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
*/
buf_size = dm_round_up((LOG_OFFSET << SECTOR_SHIFT) +
bitset_size, ti->limits.hardsect_size);
+
+ if (buf_size > dev->bdev->bd_inode->i_size) {
+ DMWARN("log device %s too small: need %llu bytes",
+ dev->name, (unsigned long long)buf_size);
+ kfree(lc);
+ return -EINVAL;
+ }
+
lc->header_location.count = buf_size >> SECTOR_SHIFT;
+
lc->io_req.mem.type = DM_IO_VMA;
+ lc->io_req.notify.fn = NULL;
lc->io_req.client = dm_io_client_create(dm_div_up(buf_size,
PAGE_SIZE));
if (IS_ERR(lc->io_req.client)) {
@@ -467,10 +481,12 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
lc->disk_header = vmalloc(buf_size);
if (!lc->disk_header) {
DMWARN("couldn't allocate disk log buffer");
+ dm_io_client_destroy(lc->io_req.client);
kfree(lc);
return -ENOMEM;
}
+ lc->io_req.mem.ptr.vma = lc->disk_header;
lc->clean_bits = (void *)lc->disk_header +
(LOG_OFFSET << SECTOR_SHIFT);
}
@@ -482,6 +498,8 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
DMWARN("couldn't allocate sync bitset");
if (!dev)
vfree(lc->clean_bits);
+ else
+ dm_io_client_destroy(lc->io_req.client);
vfree(lc->disk_header);
kfree(lc);
return -ENOMEM;
@@ -495,6 +513,8 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
vfree(lc->sync_bits);
if (!dev)
vfree(lc->clean_bits);
+ else
+ dm_io_client_destroy(lc->io_req.client);
vfree(lc->disk_header);
kfree(lc);
return -ENOMEM;
@@ -631,8 +651,10 @@ static int disk_resume(struct dm_dirty_log *log)
/* set the correct number of regions in the header */
lc->header.nr_regions = lc->region_count;
+ header_to_disk(&lc->header, lc->disk_header);
+
/* write the new header */
- r = write_header(lc);
+ r = rw_header(lc, WRITE);
if (r) {
DMWARN("%s: Failed to write header on dirty region log device",
lc->log_dev->name);
@@ -682,7 +704,7 @@ static int disk_flush(struct dm_dirty_log *log)
if (!lc->touched)
return 0;
- r = write_header(lc);
+ r = rw_header(lc, WRITE);
if (r)
fail_log_device(lc);
else
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 3d7f4923cd1..095f77bf968 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -889,7 +889,7 @@ static int fail_path(struct pgpath *pgpath)
dm_path_uevent(DM_UEVENT_PATH_FAILED, m->ti,
pgpath->path.dev->name, m->nr_valid_paths);
- queue_work(kmultipathd, &m->trigger_event);
+ schedule_work(&m->trigger_event);
queue_work(kmultipathd, &pgpath->deactivate_path);
out:
@@ -932,7 +932,7 @@ static int reinstate_path(struct pgpath *pgpath)
dm_path_uevent(DM_UEVENT_PATH_REINSTATED, m->ti,
pgpath->path.dev->name, m->nr_valid_paths);
- queue_work(kmultipathd, &m->trigger_event);
+ schedule_work(&m->trigger_event);
out:
spin_unlock_irqrestore(&m->lock, flags);
@@ -976,7 +976,7 @@ static void bypass_pg(struct multipath *m, struct priority_group *pg,
spin_unlock_irqrestore(&m->lock, flags);
- queue_work(kmultipathd, &m->trigger_event);
+ schedule_work(&m->trigger_event);
}
/*
@@ -1006,7 +1006,7 @@ static int switch_pg_num(struct multipath *m, const char *pgstr)
}
spin_unlock_irqrestore(&m->lock, flags);
- queue_work(kmultipathd, &m->trigger_event);
+ schedule_work(&m->trigger_event);
return 0;
}
@@ -1495,14 +1495,10 @@ static int __init dm_multipath_init(void)
static void __exit dm_multipath_exit(void)
{
- int r;
-
destroy_workqueue(kmpath_handlerd);
destroy_workqueue(kmultipathd);
- r = dm_unregister_target(&multipath_target);
- if (r < 0)
- DMERR("target unregister failed %d", r);
+ dm_unregister_target(&multipath_target);
kmem_cache_destroy(_mpio_cache);
}
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index ec43f9fa4b2..4d6bc101962 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -197,9 +197,6 @@ static void fail_mirror(struct mirror *m, enum dm_raid1_error error_type)
struct mirror_set *ms = m->ms;
struct mirror *new;
- if (!errors_handled(ms))
- return;
-
/*
* error_count is used for nothing more than a
* simple way to tell if a device has encountered
@@ -210,6 +207,9 @@ static void fail_mirror(struct mirror *m, enum dm_raid1_error error_type)
if (test_and_set_bit(error_type, &m->error_type))
return;
+ if (!errors_handled(ms))
+ return;
+
if (m != get_default_mirror(ms))
goto out;
@@ -808,12 +808,6 @@ static void free_context(struct mirror_set *ms, struct dm_target *ti,
kfree(ms);
}
-static inline int _check_region_size(struct dm_target *ti, uint32_t size)
-{
- return !(size % (PAGE_SIZE >> 9) || !is_power_of_2(size) ||
- size > ti->len);
-}
-
static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
unsigned int mirror, char **argv)
{
@@ -872,12 +866,6 @@ static struct dm_dirty_log *create_dirty_log(struct dm_target *ti,
return NULL;
}
- if (!_check_region_size(ti, dl->type->get_region_size(dl))) {
- ti->error = "Invalid region size";
- dm_dirty_log_destroy(dl);
- return NULL;
- }
-
return dl;
}
@@ -1300,11 +1288,7 @@ static int __init dm_mirror_init(void)
static void __exit dm_mirror_exit(void)
{
- int r;
-
- r = dm_unregister_target(&mirror_target);
- if (r < 0)
- DMERR("unregister failed %d", r);
+ dm_unregister_target(&mirror_target);
}
/* Module hooks */
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c
new file mode 100644
index 00000000000..936b34e0959
--- /dev/null
+++ b/drivers/md/dm-snap-persistent.c
@@ -0,0 +1,704 @@
+/*
+ * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
+ * Copyright (C) 2006-2008 Red Hat GmbH
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-exception-store.h"
+#include "dm-snap.h"
+
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/dm-io.h>
+
+#define DM_MSG_PREFIX "persistent snapshot"
+#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */
+
+/*-----------------------------------------------------------------
+ * Persistent snapshots, by persistent we mean that the snapshot
+ * will survive a reboot.
+ *---------------------------------------------------------------*/
+
+/*
+ * We need to store a record of which parts of the origin have
+ * been copied to the snapshot device. The snapshot code
+ * requires that we copy exception chunks to chunk aligned areas
+ * of the COW store. It makes sense therefore, to store the
+ * metadata in chunk size blocks.
+ *
+ * There is no backward or forward compatibility implemented,
+ * snapshots with different disk versions than the kernel will
+ * not be usable. It is expected that "lvcreate" will blank out
+ * the start of a fresh COW device before calling the snapshot
+ * constructor.
+ *
+ * The first chunk of the COW device just contains the header.
+ * After this there is a chunk filled with exception metadata,
+ * followed by as many exception chunks as can fit in the
+ * metadata areas.
+ *
+ * All on disk structures are in little-endian format. The end
+ * of the exceptions info is indicated by an exception with a
+ * new_chunk of 0, which is invalid since it would point to the
+ * header chunk.
+ */
+
+/*
+ * Magic for persistent snapshots: "SnAp" - Feeble isn't it.
+ */
+#define SNAP_MAGIC 0x70416e53
+
+/*
+ * The on-disk version of the metadata.
+ */
+#define SNAPSHOT_DISK_VERSION 1
+
+struct disk_header {
+ uint32_t magic;
+
+ /*
+ * Is this snapshot valid. There is no way of recovering
+ * an invalid snapshot.
+ */
+ uint32_t valid;
+
+ /*
+ * Simple, incrementing version. no backward
+ * compatibility.
+ */
+ uint32_t version;
+
+ /* In sectors */
+ uint32_t chunk_size;
+};
+
+struct disk_exception {
+ uint64_t old_chunk;
+ uint64_t new_chunk;
+};
+
+struct commit_callback {
+ void (*callback)(void *, int success);
+ void *context;
+};
+
+/*
+ * The top level structure for a persistent exception store.
+ */
+struct pstore {
+ struct dm_snapshot *snap; /* up pointer to my snapshot */
+ int version;
+ int valid;
+ uint32_t exceptions_per_area;
+
+ /*
+ * Now that we have an asynchronous kcopyd there is no
+ * need for large chunk sizes, so it wont hurt to have a
+ * whole chunks worth of metadata in memory at once.
+ */
+ void *area;
+
+ /*
+ * An area of zeros used to clear the next area.
+ */
+ void *zero_area;
+
+ /*
+ * Used to keep track of which metadata area the data in
+ * 'chunk' refers to.
+ */
+ chunk_t current_area;
+
+ /*
+ * The next free chunk for an exception.
+ */
+ chunk_t next_free;
+
+ /*
+ * The index of next free exception in the current
+ * metadata area.
+ */
+ uint32_t current_committed;
+
+ atomic_t pending_count;
+ uint32_t callback_count;
+ struct commit_callback *callbacks;
+ struct dm_io_client *io_client;
+
+ struct workqueue_struct *metadata_wq;
+};
+
+static unsigned sectors_to_pages(unsigned sectors)
+{
+ return DIV_ROUND_UP(sectors, PAGE_SIZE >> 9);
+}
+
+static int alloc_area(struct pstore *ps)
+{
+ int r = -ENOMEM;
+ size_t len;
+
+ len = ps->snap->chunk_size << SECTOR_SHIFT;
+
+ /*
+ * Allocate the chunk_size block of memory that will hold
+ * a single metadata area.
+ */
+ ps->area = vmalloc(len);
+ if (!ps->area)
+ return r;
+
+ ps->zero_area = vmalloc(len);
+ if (!ps->zero_area) {
+ vfree(ps->area);
+ return r;
+ }
+ memset(ps->zero_area, 0, len);
+
+ return 0;
+}
+
+static void free_area(struct pstore *ps)
+{
+ vfree(ps->area);
+ ps->area = NULL;
+ vfree(ps->zero_area);
+ ps->zero_area = NULL;
+}
+
+struct mdata_req {
+ struct dm_io_region *where;
+ struct dm_io_request *io_req;
+ struct work_struct work;
+ int result;
+};
+
+static void do_metadata(struct work_struct *work)
+{
+ struct mdata_req *req = container_of(work, struct mdata_req, work);
+
+ req->result = dm_io(req->io_req, 1, req->where, NULL);
+}
+
+/*
+ * Read or write a chunk aligned and sized block of data from a device.
+ */
+static int chunk_io(struct pstore *ps, chunk_t chunk, int rw, int metadata)
+{
+ struct dm_io_region where = {
+ .bdev = ps->snap->cow->bdev,
+ .sector = ps->snap->chunk_size * chunk,
+ .count = ps->snap->chunk_size,
+ };
+ struct dm_io_request io_req = {
+ .bi_rw = rw,
+ .mem.type = DM_IO_VMA,
+ .mem.ptr.vma = ps->area,
+ .client = ps->io_client,
+ .notify.fn = NULL,
+ };
+ struct mdata_req req;
+
+ if (!metadata)
+ return dm_io(&io_req, 1, &where, NULL);
+
+ req.where = &where;
+ req.io_req = &io_req;
+
+ /*
+ * Issue the synchronous I/O from a different thread
+ * to avoid generic_make_request recursion.
+ */
+ INIT_WORK(&req.work, do_metadata);
+ queue_work(ps->metadata_wq, &req.work);
+ flush_workqueue(ps->metadata_wq);
+
+ return req.result;
+}
+
+/*
+ * Convert a metadata area index to a chunk index.
+ */
+static chunk_t area_location(struct pstore *ps, chunk_t area)
+{
+ return 1 + ((ps->exceptions_per_area + 1) * area);
+}
+
+/*
+ * Read or write a metadata area. Remembering to skip the first
+ * chunk which holds the header.
+ */
+static int area_io(struct pstore *ps, int rw)
+{
+ int r;
+ chunk_t chunk;
+
+ chunk = area_location(ps, ps->current_area);
+
+ r = chunk_io(ps, chunk, rw, 0);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+static void zero_memory_area(struct pstore *ps)
+{
+ memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
+}
+
+static int zero_disk_area(struct pstore *ps, chunk_t area)
+{
+ struct dm_io_region where = {
+ .bdev = ps->snap->cow->bdev,
+ .sector = ps->snap->chunk_size * area_location(ps, area),
+ .count = ps->snap->chunk_size,
+ };
+ struct dm_io_request io_req = {
+ .bi_rw = WRITE,
+ .mem.type = DM_IO_VMA,
+ .mem.ptr.vma = ps->zero_area,
+ .client = ps->io_client,
+ .notify.fn = NULL,
+ };
+
+ return dm_io(&io_req, 1, &where, NULL);
+}
+
+static int read_header(struct pstore *ps, int *new_snapshot)
+{
+ int r;
+ struct disk_header *dh;
+ chunk_t chunk_size;
+ int chunk_size_supplied = 1;
+
+ /*
+ * Use default chunk size (or hardsect_size, if larger) if none supplied
+ */
+ if (!ps->snap->chunk_size) {
+ ps->snap->chunk_size = max(DM_CHUNK_SIZE_DEFAULT_SECTORS,
+ bdev_hardsect_size(ps->snap->cow->bdev) >> 9);
+ ps->snap->chunk_mask = ps->snap->chunk_size - 1;
+ ps->snap->chunk_shift = ffs(ps->snap->chunk_size) - 1;
+ chunk_size_supplied = 0;
+ }
+
+ ps->io_client = dm_io_client_create(sectors_to_pages(ps->snap->
+ chunk_size));
+ if (IS_ERR(ps->io_client))
+ return PTR_ERR(ps->io_client);
+
+ r = alloc_area(ps);
+ if (r)
+ return r;
+
+ r = chunk_io(ps, 0, READ, 1);
+ if (r)
+ goto bad;
+
+ dh = (struct disk_header *) ps->area;
+
+ if (le32_to_cpu(dh->magic) == 0) {
+ *new_snapshot = 1;
+ return 0;
+ }
+
+ if (le32_to_cpu(dh->magic) != SNAP_MAGIC) {
+ DMWARN("Invalid or corrupt snapshot");
+ r = -ENXIO;
+ goto bad;
+ }
+
+ *new_snapshot = 0;
+ ps->valid = le32_to_cpu(dh->valid);
+ ps->version = le32_to_cpu(dh->version);
+ chunk_size = le32_to_cpu(dh->chunk_size);
+
+ if (!chunk_size_supplied || ps->snap->chunk_size == chunk_size)
+ return 0;
+
+ DMWARN("chunk size %llu in device metadata overrides "
+ "table chunk size of %llu.",
+ (unsigned long long)chunk_size,
+ (unsigned long long)ps->snap->chunk_size);
+
+ /* We had a bogus chunk_size. Fix stuff up. */
+ free_area(ps);
+
+ ps->snap->chunk_size = chunk_size;
+ ps->snap->chunk_mask = chunk_size - 1;
+ ps->snap->chunk_shift = ffs(chunk_size) - 1;
+
+ r = dm_io_client_resize(sectors_to_pages(ps->snap->chunk_size),
+ ps->io_client);
+ if (r)
+ return r;
+
+ r = alloc_area(ps);
+ return r;
+
+bad:
+ free_area(ps);
+ return r;
+}
+
+static int write_header(struct pstore *ps)
+{
+ struct disk_header *dh;
+
+ memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
+
+ dh = (struct disk_header *) ps->area;
+ dh->magic = cpu_to_le32(SNAP_MAGIC);
+ dh->valid = cpu_to_le32(ps->valid);
+ dh->version = cpu_to_le32(ps->version);
+ dh->chunk_size = cpu_to_le32(ps->snap->chunk_size);
+
+ return chunk_io(ps, 0, WRITE, 1);
+}
+
+/*
+ * Access functions for the disk exceptions, these do the endian conversions.
+ */
+static struct disk_exception *get_exception(struct pstore *ps, uint32_t index)
+{
+ BUG_ON(index >= ps->exceptions_per_area);
+
+ return ((struct disk_exception *) ps->area) + index;
+}
+
+static void read_exception(struct pstore *ps,
+ uint32_t index, struct disk_exception *result)
+{
+ struct disk_exception *e = get_exception(ps, index);
+
+ /* copy it */
+ result->old_chunk = le64_to_cpu(e->old_chunk);
+ result->new_chunk = le64_to_cpu(e->new_chunk);
+}
+
+static void write_exception(struct pstore *ps,
+ uint32_t index, struct disk_exception *de)
+{
+ struct disk_exception *e = get_exception(ps, index);
+
+ /* copy it */
+ e->old_chunk = cpu_to_le64(de->old_chunk);
+ e->new_chunk = cpu_to_le64(de->new_chunk);
+}
+
+/*
+ * Registers the exceptions that are present in the current area.
+ * 'full' is filled in to indicate if the area has been
+ * filled.
+ */
+static int insert_exceptions(struct pstore *ps,
+ int (*callback)(void *callback_context,
+ chunk_t old, chunk_t new),
+ void *callback_context,
+ int *full)
+{
+ int r;
+ unsigned int i;
+ struct disk_exception de;
+
+ /* presume the area is full */
+ *full = 1;
+
+ for (i = 0; i < ps->exceptions_per_area; i++) {
+ read_exception(ps, i, &de);
+
+ /*
+ * If the new_chunk is pointing at the start of
+ * the COW device, where the first metadata area
+ * is we know that we've hit the end of the
+ * exceptions. Therefore the area is not full.
+ */
+ if (de.new_chunk == 0LL) {
+ ps->current_committed = i;
+ *full = 0;
+ break;
+ }
+
+ /*
+ * Keep track of the start of the free chunks.
+ */
+ if (ps->next_free <= de.new_chunk)
+ ps->next_free = de.new_chunk + 1;
+
+ /*
+ * Otherwise we add the exception to the snapshot.
+ */
+ r = callback(callback_context, de.old_chunk, de.new_chunk);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
+static int read_exceptions(struct pstore *ps,
+ int (*callback)(void *callback_context, chunk_t old,
+ chunk_t new),
+ void *callback_context)
+{
+ int r, full = 1;
+
+ /*
+ * Keeping reading chunks and inserting exceptions until
+ * we find a partially full area.
+ */
+ for (ps->current_area = 0; full; ps->current_area++) {
+ r = area_io(ps, READ);
+ if (r)
+ return r;
+
+ r = insert_exceptions(ps, callback, callback_context, &full);
+ if (r)
+ return r;
+ }
+
+ ps->current_area--;
+
+ return 0;
+}
+
+static struct pstore *get_info(struct dm_exception_store *store)
+{
+ return (struct pstore *) store->context;
+}
+
+static void persistent_fraction_full(struct dm_exception_store *store,
+ sector_t *numerator, sector_t *denominator)
+{
+ *numerator = get_info(store)->next_free * store->snap->chunk_size;
+ *denominator = get_dev_size(store->snap->cow->bdev);
+}
+
+static void persistent_destroy(struct dm_exception_store *store)
+{
+ struct pstore *ps = get_info(store);
+
+ destroy_workqueue(ps->metadata_wq);
+ dm_io_client_destroy(ps->io_client);
+ vfree(ps->callbacks);
+ free_area(ps);
+ kfree(ps);
+}
+
+static int persistent_read_metadata(struct dm_exception_store *store,
+ int (*callback)(void *callback_context,
+ chunk_t old, chunk_t new),
+ void *callback_context)
+{
+ int r, uninitialized_var(new_snapshot);
+ struct pstore *ps = get_info(store);
+
+ /*
+ * Read the snapshot header.
+ */
+ r = read_header(ps, &new_snapshot);
+ if (r)
+ return r;
+
+ /*
+ * Now we know correct chunk_size, complete the initialisation.
+ */
+ ps->exceptions_per_area = (ps->snap->chunk_size << SECTOR_SHIFT) /
+ sizeof(struct disk_exception);
+ ps->callbacks = dm_vcalloc(ps->exceptions_per_area,
+ sizeof(*ps->callbacks));
+ if (!ps->callbacks)
+ return -ENOMEM;
+
+ /*
+ * Do we need to setup a new snapshot ?
+ */
+ if (new_snapshot) {
+ r = write_header(ps);
+ if (r) {
+ DMWARN("write_header failed");
+ return r;
+ }
+
+ ps->current_area = 0;
+ zero_memory_area(ps);
+ r = zero_disk_area(ps, 0);
+ if (r) {
+ DMWARN("zero_disk_area(0) failed");
+ return r;
+ }
+ } else {
+ /*
+ * Sanity checks.
+ */
+ if (ps->version != SNAPSHOT_DISK_VERSION) {
+ DMWARN("unable to handle snapshot disk version %d",
+ ps->version);
+ return -EINVAL;
+ }
+
+ /*
+ * Metadata are valid, but snapshot is invalidated
+ */
+ if (!ps->valid)
+ return 1;
+
+ /*
+ * Read the metadata.
+ */
+ r = read_exceptions(ps, callback, callback_context);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
+static int persistent_prepare_exception(struct dm_exception_store *store,
+ struct dm_snap_exception *e)
+{
+ struct pstore *ps = get_info(store);
+ uint32_t stride;
+ chunk_t next_free;
+ sector_t size = get_dev_size(store->snap->cow->bdev);
+
+ /* Is there enough room ? */
+ if (size < ((ps->next_free + 1) * store->snap->chunk_size))
+ return -ENOSPC;
+
+ e->new_chunk = ps->next_free;
+
+ /*
+ * Move onto the next free pending, making sure to take
+ * into account the location of the metadata chunks.
+ */
+ stride = (ps->exceptions_per_area + 1);
+ next_free = ++ps->next_free;
+ if (sector_div(next_free, stride) == 1)
+ ps->next_free++;
+
+ atomic_inc(&ps->pending_count);
+ return 0;
+}
+
+static void persistent_commit_exception(struct dm_exception_store *store,
+ struct dm_snap_exception *e,
+ void (*callback) (void *, int success),
+ void *callback_context)
+{
+ unsigned int i;
+ struct pstore *ps = get_info(store);
+ struct disk_exception de;
+ struct commit_callback *cb;
+
+ de.old_chunk = e->old_chunk;
+ de.new_chunk = e->new_chunk;
+ write_exception(ps, ps->current_committed++, &de);
+
+ /*
+ * Add the callback to the back of the array. This code
+ * is the only place where the callback array is
+ * manipulated, and we know that it will never be called
+ * multiple times concurrently.
+ */
+ cb = ps->callbacks + ps->callback_count++;
+ cb->callback = callback;
+ cb->context = callback_context;
+
+ /*
+ * If there are exceptions in flight and we have not yet
+ * filled this metadata area there's nothing more to do.
+ */
+ if (!atomic_dec_and_test(&ps->pending_count) &&
+ (ps->current_committed != ps->exceptions_per_area))
+ return;
+
+ /*
+ * If we completely filled the current area, then wipe the next one.
+ */
+ if ((ps->current_committed == ps->exceptions_per_area) &&
+ zero_disk_area(ps, ps->current_area + 1))
+ ps->valid = 0;
+
+ /*
+ * Commit exceptions to disk.
+ */
+ if (ps->valid && area_io(ps, WRITE))
+ ps->valid = 0;
+
+ /*
+ * Advance to the next area if this one is full.
+ */
+ if (ps->current_committed == ps->exceptions_per_area) {
+ ps->current_committed = 0;
+ ps->current_area++;
+ zero_memory_area(ps);
+ }
+
+ for (i = 0; i < ps->callback_count; i++) {
+ cb = ps->callbacks + i;
+ cb->callback(cb->context, ps->valid);
+ }
+
+ ps->callback_count = 0;
+}
+
+static void persistent_drop_snapshot(struct dm_exception_store *store)
+{
+ struct pstore *ps = get_info(store);
+
+ ps->valid = 0;
+ if (write_header(ps))
+ DMWARN("write header failed");
+}
+
+int dm_create_persistent(struct dm_exception_store *store)
+{
+ struct pstore *ps;
+
+ /* allocate the pstore */
+ ps = kmalloc(sizeof(*ps), GFP_KERNEL);
+ if (!ps)
+ return -ENOMEM;
+
+ ps->snap = store->snap;
+ ps->valid = 1;
+ ps->version = SNAPSHOT_DISK_VERSION;
+ ps->area = NULL;
+ ps->next_free = 2; /* skipping the header and first area */
+ ps->current_committed = 0;
+
+ ps->callback_count = 0;
+ atomic_set(&ps->pending_count, 0);
+ ps->callbacks = NULL;
+
+ ps->metadata_wq = create_singlethread_workqueue("ksnaphd");
+ if (!ps->metadata_wq) {
+ kfree(ps);
+ DMERR("couldn't start header metadata update thread");
+ return -ENOMEM;
+ }
+
+ store->destroy = persistent_destroy;
+ store->read_metadata = persistent_read_metadata;
+ store->prepare_exception = persistent_prepare_exception;
+ store->commit_exception = persistent_commit_exception;
+ store->drop_snapshot = persistent_drop_snapshot;
+ store->fraction_full = persistent_fraction_full;
+ store->context = ps;
+
+ return 0;
+}
+
+int dm_persistent_snapshot_init(void)
+{
+ return 0;
+}
+
+void dm_persistent_snapshot_exit(void)
+{
+}
diff --git a/drivers/md/dm-snap-transient.c b/drivers/md/dm-snap-transient.c
new file mode 100644
index 00000000000..7f6e2e6dcb0
--- /dev/null
+++ b/drivers/md/dm-snap-transient.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
+ * Copyright (C) 2006-2008 Red Hat GmbH
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-exception-store.h"
+#include "dm-snap.h"
+
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/dm-io.h>
+
+#define DM_MSG_PREFIX "transient snapshot"
+
+/*-----------------------------------------------------------------
+ * Implementation of the store for non-persistent snapshots.
+ *---------------------------------------------------------------*/
+struct transient_c {
+ sector_t next_free;
+};
+
+static void transient_destroy(struct dm_exception_store *store)
+{
+ kfree(store->context);
+}
+
+static int transient_read_metadata(struct dm_exception_store *store,
+ int (*callback)(void *callback_context,
+ chunk_t old, chunk_t new),
+ void *callback_context)
+{
+ return 0;
+}
+
+static int transient_prepare_exception(struct dm_exception_store *store,
+ struct dm_snap_exception *e)
+{
+ struct transient_c *tc = (struct transient_c *) store->context;
+ sector_t size = get_dev_size(store->snap->cow->bdev);
+
+ if (size < (tc->next_free + store->snap->chunk_size))
+ return -1;
+
+ e->new_chunk = sector_to_chunk(store->snap, tc->next_free);
+ tc->next_free += store->snap->chunk_size;
+
+ return 0;
+}
+
+static void transient_commit_exception(struct dm_exception_store *store,
+ struct dm_snap_exception *e,
+ void (*callback) (void *, int success),
+ void *callback_context)
+{
+ /* Just succeed */
+ callback(callback_context, 1);
+}
+
+static void transient_fraction_full(struct dm_exception_store *store,
+ sector_t *numerator, sector_t *denominator)
+{
+ *numerator = ((struct transient_c *) store->context)->next_free;
+ *denominator = get_dev_size(store->snap->cow->bdev);
+}
+
+int dm_create_transient(struct dm_exception_store *store)
+{
+ struct transient_c *tc;
+
+ store->destroy = transient_destroy;
+ store->read_metadata = transient_read_metadata;
+ store->prepare_exception = transient_prepare_exception;
+ store->commit_exception = transient_commit_exception;
+ store->drop_snapshot = NULL;
+ store->fraction_full = transient_fraction_full;
+
+ tc = kmalloc(sizeof(struct transient_c), GFP_KERNEL);
+ if (!tc)
+ return -ENOMEM;
+
+ tc->next_free = 0;
+ store->context = tc;
+
+ return 0;
+}
+
+int dm_transient_snapshot_init(void)
+{
+ return 0;
+}
+
+void dm_transient_snapshot_exit(void)
+{
+}
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 6c96db26b87..65ff82ff124 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -9,6 +9,7 @@
#include <linux/blkdev.h>
#include <linux/ctype.h>
#include <linux/device-mapper.h>
+#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kdev_t.h>
@@ -20,6 +21,7 @@
#include <linux/log2.h>
#include <linux/dm-kcopyd.h>
+#include "dm-exception-store.h"
#include "dm-snap.h"
#include "dm-bio-list.h"
@@ -428,8 +430,13 @@ out:
list_add(&new_e->hash_list, e ? &e->hash_list : l);
}
-int dm_add_exception(struct dm_snapshot *s, chunk_t old, chunk_t new)
+/*
+ * Callback used by the exception stores to load exceptions when
+ * initialising.
+ */
+static int dm_add_exception(void *context, chunk_t old, chunk_t new)
{
+ struct dm_snapshot *s = context;
struct dm_snap_exception *e;
e = alloc_exception();
@@ -658,7 +665,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
spin_lock_init(&s->tracked_chunk_lock);
/* Metadata must only be loaded into one table at once */
- r = s->store.read_metadata(&s->store);
+ r = s->store.read_metadata(&s->store, dm_add_exception, (void *)s);
if (r < 0) {
ti->error = "Failed to read snapshot metadata";
goto bad_load_and_register;
@@ -735,7 +742,7 @@ static void snapshot_dtr(struct dm_target *ti)
unregister_snapshot(s);
while (atomic_read(&s->pending_exceptions_count))
- yield();
+ msleep(1);
/*
* Ensure instructions in mempool_destroy aren't reordered
* before atomic_read.
@@ -888,10 +895,10 @@ static void pending_complete(struct dm_snap_pending_exception *pe, int success)
/*
* Check for conflicting reads. This is extremely improbable,
- * so yield() is sufficient and there is no need for a wait queue.
+ * so msleep(1) is sufficient and there is no need for a wait queue.
*/
while (__chunk_is_tracked(s, pe->e.old_chunk))
- yield();
+ msleep(1);
/*
* Add a proper exception, and remove the
@@ -1404,6 +1411,12 @@ static int __init dm_snapshot_init(void)
{
int r;
+ r = dm_exception_store_init();
+ if (r) {
+ DMERR("Failed to initialize exception stores");
+ return r;
+ }
+
r = dm_register_target(&snapshot_target);
if (r) {
DMERR("snapshot target register failed %d", r);
@@ -1452,39 +1465,34 @@ static int __init dm_snapshot_init(void)
return 0;
- bad_pending_pool:
+bad_pending_pool:
kmem_cache_destroy(tracked_chunk_cache);
- bad5:
+bad5:
kmem_cache_destroy(pending_cache);
- bad4:
+bad4:
kmem_cache_destroy(exception_cache);
- bad3:
+bad3:
exit_origin_hash();
- bad2:
+bad2:
dm_unregister_target(&origin_target);
- bad1:
+bad1:
dm_unregister_target(&snapshot_target);
return r;
}
static void __exit dm_snapshot_exit(void)
{
- int r;
-
destroy_workqueue(ksnapd);
- r = dm_unregister_target(&snapshot_target);
- if (r)
- DMERR("snapshot unregister failed %d", r);
-
- r = dm_unregister_target(&origin_target);
- if (r)
- DMERR("origin unregister failed %d", r);
+ dm_unregister_target(&snapshot_target);
+ dm_unregister_target(&origin_target);
exit_origin_hash();
kmem_cache_destroy(pending_cache);
kmem_cache_destroy(exception_cache);
kmem_cache_destroy(tracked_chunk_cache);
+
+ dm_exception_store_exit();
}
/* Module hooks */
diff --git a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h
index 99c0106ede2..d9e62b43cf8 100644
--- a/drivers/md/dm-snap.h
+++ b/drivers/md/dm-snap.h
@@ -1,6 +1,4 @@
/*
- * dm-snapshot.c
- *
* Copyright (C) 2001-2002 Sistina Software (UK) Limited.
*
* This file is released under the GPL.
@@ -10,6 +8,7 @@
#define DM_SNAPSHOT_H
#include <linux/device-mapper.h>
+#include "dm-exception-store.h"
#include "dm-bio-list.h"
#include <linux/blkdev.h>
#include <linux/workqueue.h>
@@ -20,116 +19,6 @@ struct exception_table {
struct list_head *table;
};
-/*
- * The snapshot code deals with largish chunks of the disk at a
- * time. Typically 32k - 512k.
- */
-typedef sector_t chunk_t;
-
-/*
- * An exception is used where an old chunk of data has been
- * replaced by a new one.
- * If chunk_t is 64 bits in size, the top 8 bits of new_chunk hold the number
- * of chunks that follow contiguously. Remaining bits hold the number of the
- * chunk within the device.
- */
-struct dm_snap_exception {
- struct list_head hash_list;
-
- chunk_t old_chunk;
- chunk_t new_chunk;
-};
-
-/*
- * Funtions to manipulate consecutive chunks
- */
-# if defined(CONFIG_LBD) || (BITS_PER_LONG == 64)
-# define DM_CHUNK_CONSECUTIVE_BITS 8
-# define DM_CHUNK_NUMBER_BITS 56
-
-static inline chunk_t dm_chunk_number(chunk_t chunk)
-{
- return chunk & (chunk_t)((1ULL << DM_CHUNK_NUMBER_BITS) - 1ULL);
-}
-
-static inline unsigned dm_consecutive_chunk_count(struct dm_snap_exception *e)
-{
- return e->new_chunk >> DM_CHUNK_NUMBER_BITS;
-}
-
-static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e)
-{
- e->new_chunk += (1ULL << DM_CHUNK_NUMBER_BITS);
-
- BUG_ON(!dm_consecutive_chunk_count(e));
-}
-
-# else
-# define DM_CHUNK_CONSECUTIVE_BITS 0
-
-static inline chunk_t dm_chunk_number(chunk_t chunk)
-{
- return chunk;
-}
-
-static inline unsigned dm_consecutive_chunk_count(struct dm_snap_exception *e)
-{
- return 0;
-}
-
-static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e)
-{
-}
-
-# endif
-
-/*
- * Abstraction to handle the meta/layout of exception stores (the
- * COW device).
- */
-struct exception_store {
-
- /*
- * Destroys this object when you've finished with it.
- */
- void (*destroy) (struct exception_store *store);
-
- /*
- * The target shouldn't read the COW device until this is
- * called.
- */
- int (*read_metadata) (struct exception_store *store);
-
- /*
- * Find somewhere to store the next exception.
- */
- int (*prepare_exception) (struct exception_store *store,
- struct dm_snap_exception *e);
-
- /*
- * Update the metadata with this exception.
- */
- void (*commit_exception) (struct exception_store *store,
- struct dm_snap_exception *e,
- void (*callback) (void *, int success),
- void *callback_context);
-
- /*
- * The snapshot is invalid, note this in the metadata.
- */
- void (*drop_snapshot) (struct exception_store *store);
-
- /*
- * Return how full the snapshot is.
- */
- void (*fraction_full) (struct exception_store *store,
- sector_t *numerator,
- sector_t *denominator);
-
- struct dm_snapshot *snap;
- void *context;
-};
-
#define DM_TRACKED_CHUNK_HASH_SIZE 16
#define DM_TRACKED_CHUNK_HASH(x) ((unsigned long)(x) & \
(DM_TRACKED_CHUNK_HASH_SIZE - 1))
@@ -172,7 +61,7 @@ struct dm_snapshot {
spinlock_t pe_lock;
/* The on disk metadata handler */
- struct exception_store store;
+ struct dm_exception_store store;
struct dm_kcopyd_client *kcopyd_client;
@@ -187,20 +76,6 @@ struct dm_snapshot {
};
/*
- * Used by the exception stores to load exceptions hen
- * initialising.
- */
-int dm_add_exception(struct dm_snapshot *s, chunk_t old, chunk_t new);
-
-/*
- * Constructor and destructor for the default persistent
- * store.
- */
-int dm_create_persistent(struct exception_store *store);
-
-int dm_create_transient(struct exception_store *store);
-
-/*
* Return the number of sectors in the device.
*/
static inline sector_t get_dev_size(struct block_device *bdev)
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index 9e4ef88d421..41569bc60ab 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -337,9 +337,7 @@ int __init dm_stripe_init(void)
void dm_stripe_exit(void)
{
- if (dm_unregister_target(&stripe_target))
- DMWARN("target unregistration failed");
-
+ dm_unregister_target(&stripe_target);
destroy_workqueue(kstriped);
return;
diff --git a/drivers/md/dm-sysfs.c b/drivers/md/dm-sysfs.c
new file mode 100644
index 00000000000..a2a45e6c7c8
--- /dev/null
+++ b/drivers/md/dm-sysfs.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/sysfs.h>
+#include <linux/dm-ioctl.h>
+#include "dm.h"
+
+struct dm_sysfs_attr {
+ struct attribute attr;
+ ssize_t (*show)(struct mapped_device *, char *);
+ ssize_t (*store)(struct mapped_device *, char *);
+};
+
+#define DM_ATTR_RO(_name) \
+struct dm_sysfs_attr dm_attr_##_name = \
+ __ATTR(_name, S_IRUGO, dm_attr_##_name##_show, NULL)
+
+static ssize_t dm_attr_show(struct kobject *kobj, struct attribute *attr,
+ char *page)
+{
+ struct dm_sysfs_attr *dm_attr;
+ struct mapped_device *md;
+ ssize_t ret;
+
+ dm_attr = container_of(attr, struct dm_sysfs_attr, attr);
+ if (!dm_attr->show)
+ return -EIO;
+
+ md = dm_get_from_kobject(kobj);
+ if (!md)
+ return -EINVAL;
+
+ ret = dm_attr->show(md, page);
+ dm_put(md);
+
+ return ret;
+}
+
+static ssize_t dm_attr_name_show(struct mapped_device *md, char *buf)
+{
+ if (dm_copy_name_and_uuid(md, buf, NULL))
+ return -EIO;
+
+ strcat(buf, "\n");
+ return strlen(buf);
+}
+
+static ssize_t dm_attr_uuid_show(struct mapped_device *md, char *buf)
+{
+ if (dm_copy_name_and_uuid(md, NULL, buf))
+ return -EIO;
+
+ strcat(buf, "\n");
+ return strlen(buf);
+}
+
+static DM_ATTR_RO(name);
+static DM_ATTR_RO(uuid);
+
+static struct attribute *dm_attrs[] = {
+ &dm_attr_name.attr,
+ &dm_attr_uuid.attr,
+ NULL,
+};
+
+static struct sysfs_ops dm_sysfs_ops = {
+ .show = dm_attr_show,
+};
+
+/*
+ * dm kobject is embedded in mapped_device structure
+ * no need to define release function here
+ */
+static struct kobj_type dm_ktype = {
+ .sysfs_ops = &dm_sysfs_ops,
+ .default_attrs = dm_attrs,
+};
+
+/*
+ * Initialize kobj
+ * because nobody using md yet, no need to call explicit dm_get/put
+ */
+int dm_sysfs_init(struct mapped_device *md)
+{
+ return kobject_init_and_add(dm_kobject(md), &dm_ktype,
+ &disk_to_dev(dm_disk(md))->kobj,
+ "%s", "dm");
+}
+
+/*
+ * Remove kobj, called after all references removed
+ */
+void dm_sysfs_exit(struct mapped_device *md)
+{
+ kobject_put(dm_kobject(md));
+}
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 04e5fd742c2..2fd66c30f7f 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
- * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
*
* This file is released under the GPL.
*/
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
+#include <linux/delay.h>
#include <asm/atomic.h>
#define DM_MSG_PREFIX "table"
@@ -24,6 +25,19 @@
#define KEYS_PER_NODE (NODE_SIZE / sizeof(sector_t))
#define CHILDREN_PER_NODE (KEYS_PER_NODE + 1)
+/*
+ * The table has always exactly one reference from either mapped_device->map
+ * or hash_cell->new_map. This reference is not counted in table->holders.
+ * A pair of dm_create_table/dm_destroy_table functions is used for table
+ * creation/destruction.
+ *
+ * Temporary references from the other code increase table->holders. A pair
+ * of dm_table_get/dm_table_put functions is used to manipulate it.
+ *
+ * When the table is about to be destroyed, we wait for table->holders to
+ * drop to zero.
+ */
+
struct dm_table {
struct mapped_device *md;
atomic_t holders;
@@ -38,6 +52,8 @@ struct dm_table {
sector_t *highs;
struct dm_target *targets;
+ unsigned barriers_supported:1;
+
/*
* Indicates the rw permissions for the new logical
* device. This should be a combination of FMODE_READ
@@ -226,7 +242,8 @@ int dm_table_create(struct dm_table **result, fmode_t mode,
return -ENOMEM;
INIT_LIST_HEAD(&t->devices);
- atomic_set(&t->holders, 1);
+ atomic_set(&t->holders, 0);
+ t->barriers_supported = 1;
if (!num_targets)
num_targets = KEYS_PER_NODE;
@@ -256,10 +273,14 @@ static void free_devices(struct list_head *devices)
}
}
-static void table_destroy(struct dm_table *t)
+void dm_table_destroy(struct dm_table *t)
{
unsigned int i;
+ while (atomic_read(&t->holders))
+ msleep(1);
+ smp_mb();
+
/* free the indexes (see dm_table_complete) */
if (t->depth >= 2)
vfree(t->index[t->depth - 2]);
@@ -297,8 +318,8 @@ void dm_table_put(struct dm_table *t)
if (!t)
return;
- if (atomic_dec_and_test(&t->holders))
- table_destroy(t);
+ smp_mb__before_atomic_dec();
+ atomic_dec(&t->holders);
}
/*
@@ -728,6 +749,10 @@ int dm_table_add_target(struct dm_table *t, const char *type,
/* FIXME: the plan is to combine high here and then have
* the merge fn apply the target level restrictions. */
combine_restrictions_low(&t->limits, &tgt->limits);
+
+ if (!(tgt->type->features & DM_TARGET_SUPPORTS_BARRIERS))
+ t->barriers_supported = 0;
+
return 0;
bad:
@@ -772,6 +797,12 @@ int dm_table_complete(struct dm_table *t)
check_for_valid_limits(&t->limits);
+ /*
+ * We only support barriers if there is exactly one underlying device.
+ */
+ if (!list_is_singular(&t->devices))
+ t->barriers_supported = 0;
+
/* how many indexes will the btree have ? */
leaf_nodes = dm_div_up(t->num_targets, KEYS_PER_NODE);
t->depth = 1 + int_log(leaf_nodes, CHILDREN_PER_NODE);
@@ -986,6 +1017,12 @@ struct mapped_device *dm_table_get_md(struct dm_table *t)
return t->md;
}
+int dm_table_barrier_ok(struct dm_table *t)
+{
+ return t->barriers_supported;
+}
+EXPORT_SYMBOL(dm_table_barrier_ok);
+
EXPORT_SYMBOL(dm_vcalloc);
EXPORT_SYMBOL(dm_get_device);
EXPORT_SYMBOL(dm_put_device);
diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c
index 835cf95b857..7decf10006e 100644
--- a/drivers/md/dm-target.c
+++ b/drivers/md/dm-target.c
@@ -130,26 +130,26 @@ int dm_register_target(struct target_type *t)
return rv;
}
-int dm_unregister_target(struct target_type *t)
+void dm_unregister_target(struct target_type *t)
{
struct tt_internal *ti;
down_write(&_lock);
if (!(ti = __find_target_type(t->name))) {
- up_write(&_lock);
- return -EINVAL;
+ DMCRIT("Unregistering unrecognised target: %s", t->name);
+ BUG();
}
if (ti->use) {
- up_write(&_lock);
- return -ETXTBSY;
+ DMCRIT("Attempt to unregister target still in use: %s",
+ t->name);
+ BUG();
}
list_del(&ti->list);
kfree(ti);
up_write(&_lock);
- return 0;
}
/*
@@ -187,8 +187,7 @@ int __init dm_target_init(void)
void dm_target_exit(void)
{
- if (dm_unregister_target(&error_target))
- DMWARN("error target unregistration failed");
+ dm_unregister_target(&error_target);
}
EXPORT_SYMBOL(dm_register_target);
diff --git a/drivers/md/dm-zero.c b/drivers/md/dm-zero.c
index cdbf126ec10..bbc97030c0c 100644
--- a/drivers/md/dm-zero.c
+++ b/drivers/md/dm-zero.c
@@ -69,10 +69,7 @@ static int __init dm_zero_init(void)
static void __exit dm_zero_exit(void)
{
- int r = dm_unregister_target(&zero_target);
-
- if (r < 0)
- DMERR("unregister failed %d", r);
+ dm_unregister_target(&zero_target);
}
module_init(dm_zero_init)
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 421c9f02d8c..51ba1db4b3e 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001, 2002 Sistina Software (UK) Limited.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
*
* This file is released under the GPL.
*/
@@ -32,6 +32,7 @@ static unsigned int _major = 0;
static DEFINE_SPINLOCK(_minor_lock);
/*
+ * For bio-based dm.
* One of these is allocated per bio.
*/
struct dm_io {
@@ -43,6 +44,7 @@ struct dm_io {
};
/*
+ * For bio-based dm.
* One of these is allocated per target within a bio. Hopefully
* this will be simplified out one day.
*/
@@ -54,6 +56,27 @@ struct dm_target_io {
DEFINE_TRACE(block_bio_complete);
+/*
+ * For request-based dm.
+ * One of these is allocated per request.
+ */
+struct dm_rq_target_io {
+ struct mapped_device *md;
+ struct dm_target *ti;
+ struct request *orig, clone;
+ int error;
+ union map_info info;
+};
+
+/*
+ * For request-based dm.
+ * One of these is allocated per bio.
+ */
+struct dm_rq_clone_bio_info {
+ struct bio *orig;
+ struct request *rq;
+};
+
union map_info *dm_get_mapinfo(struct bio *bio)
{
if (bio && bio->bi_private)
@@ -144,11 +167,16 @@ struct mapped_device {
/* forced geometry settings */
struct hd_geometry geometry;
+
+ /* sysfs handle */
+ struct kobject kobj;
};
#define MIN_IOS 256
static struct kmem_cache *_io_cache;
static struct kmem_cache *_tio_cache;
+static struct kmem_cache *_rq_tio_cache;
+static struct kmem_cache *_rq_bio_info_cache;
static int __init local_init(void)
{
@@ -164,9 +192,17 @@ static int __init local_init(void)
if (!_tio_cache)
goto out_free_io_cache;
+ _rq_tio_cache = KMEM_CACHE(dm_rq_target_io, 0);
+ if (!_rq_tio_cache)
+ goto out_free_tio_cache;
+
+ _rq_bio_info_cache = KMEM_CACHE(dm_rq_clone_bio_info, 0);
+ if (!_rq_bio_info_cache)
+ goto out_free_rq_tio_cache;
+
r = dm_uevent_init();
if (r)
- goto out_free_tio_cache;
+ goto out_free_rq_bio_info_cache;
_major = major;
r = register_blkdev(_major, _name);
@@ -180,6 +216,10 @@ static int __init local_init(void)
out_uevent_exit:
dm_uevent_exit();
+out_free_rq_bio_info_cache:
+ kmem_cache_destroy(_rq_bio_info_cache);
+out_free_rq_tio_cache:
+ kmem_cache_destroy(_rq_tio_cache);
out_free_tio_cache:
kmem_cache_destroy(_tio_cache);
out_free_io_cache:
@@ -190,6 +230,8 @@ out_free_io_cache:
static void local_exit(void)
{
+ kmem_cache_destroy(_rq_bio_info_cache);
+ kmem_cache_destroy(_rq_tio_cache);
kmem_cache_destroy(_tio_cache);
kmem_cache_destroy(_io_cache);
unregister_blkdev(_major, _name);
@@ -796,7 +838,11 @@ static int __split_bio(struct mapped_device *md, struct bio *bio)
ci.map = dm_get_table(md);
if (unlikely(!ci.map))
return -EIO;
-
+ if (unlikely(bio_barrier(bio) && !dm_table_barrier_ok(ci.map))) {
+ dm_table_put(ci.map);
+ bio_endio(bio, -EOPNOTSUPP);
+ return 0;
+ }
ci.md = md;
ci.bio = bio;
ci.io = alloc_io(md);
@@ -880,15 +926,6 @@ static int dm_request(struct request_queue *q, struct bio *bio)
struct mapped_device *md = q->queuedata;
int cpu;
- /*
- * There is no use in forwarding any barrier request since we can't
- * guarantee it is (or can be) handled by the targets correctly.
- */
- if (unlikely(bio_barrier(bio))) {
- bio_endio(bio, -EOPNOTSUPP);
- return 0;
- }
-
down_read(&md->io_lock);
cpu = part_stat_lock();
@@ -943,8 +980,6 @@ static int dm_any_congested(void *congested_data, int bdi_bits)
struct mapped_device *md = congested_data;
struct dm_table *map;
- atomic_inc(&md->pending);
-
if (!test_bit(DMF_BLOCK_IO, &md->flags)) {
map = dm_get_table(md);
if (map) {
@@ -953,10 +988,6 @@ static int dm_any_congested(void *congested_data, int bdi_bits)
}
}
- if (!atomic_dec_return(&md->pending))
- /* nudge anyone waiting on suspend queue */
- wake_up(&md->wait);
-
return r;
}
@@ -1216,10 +1247,12 @@ static int __bind(struct mapped_device *md, struct dm_table *t)
if (md->suspended_bdev)
__set_size(md, size);
- if (size == 0)
+
+ if (!size) {
+ dm_table_destroy(t);
return 0;
+ }
- dm_table_get(t);
dm_table_event_callback(t, event_callback, md);
write_lock(&md->map_lock);
@@ -1241,7 +1274,7 @@ static void __unbind(struct mapped_device *md)
write_lock(&md->map_lock);
md->map = NULL;
write_unlock(&md->map_lock);
- dm_table_put(map);
+ dm_table_destroy(map);
}
/*
@@ -1255,6 +1288,8 @@ int dm_create(int minor, struct mapped_device **result)
if (!md)
return -ENXIO;
+ dm_sysfs_init(md);
+
*result = md;
return 0;
}
@@ -1330,8 +1365,9 @@ void dm_put(struct mapped_device *md)
dm_table_presuspend_targets(map);
dm_table_postsuspend_targets(map);
}
- __unbind(md);
+ dm_sysfs_exit(md);
dm_table_put(map);
+ __unbind(md);
free_dev(md);
}
}
@@ -1669,6 +1705,27 @@ struct gendisk *dm_disk(struct mapped_device *md)
return md->disk;
}
+struct kobject *dm_kobject(struct mapped_device *md)
+{
+ return &md->kobj;
+}
+
+/*
+ * struct mapped_device should not be exported outside of dm.c
+ * so use this check to verify that kobj is part of md structure
+ */
+struct mapped_device *dm_get_from_kobject(struct kobject *kobj)
+{
+ struct mapped_device *md;
+
+ md = container_of(kobj, struct mapped_device, kobj);
+ if (&md->kobj != kobj)
+ return NULL;
+
+ dm_get(md);
+ return md;
+}
+
int dm_suspended(struct mapped_device *md)
{
return test_bit(DMF_SUSPENDED, &md->flags);
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 0ade60cdef4..20194e000c5 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -36,6 +36,7 @@ struct dm_table;
/*-----------------------------------------------------------------
* Internal table functions.
*---------------------------------------------------------------*/
+void dm_table_destroy(struct dm_table *t);
void dm_table_event_callback(struct dm_table *t,
void (*fn)(void *), void *context);
struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index);
@@ -51,6 +52,7 @@ int dm_table_any_congested(struct dm_table *t, int bdi_bits);
* To check the return value from dm_table_find_target().
*/
#define dm_target_is_valid(t) ((t)->table)
+int dm_table_barrier_ok(struct dm_table *t);
/*-----------------------------------------------------------------
* A registry of target types.
@@ -72,6 +74,14 @@ int dm_interface_init(void);
void dm_interface_exit(void);
/*
+ * sysfs interface
+ */
+int dm_sysfs_init(struct mapped_device *md);
+void dm_sysfs_exit(struct mapped_device *md);
+struct kobject *dm_kobject(struct mapped_device *md);
+struct mapped_device *dm_get_from_kobject(struct kobject *kobj);
+
+/*
* Targets for linear and striped mappings
*/
int dm_linear_init(void);
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
index 56faef1a1d5..06c655c5558 100644
--- a/drivers/message/i2o/exec-osm.c
+++ b/drivers/message/i2o/exec-osm.c
@@ -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.
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index f3384c32b9a..efba7021948 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -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
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index 6e53a30bfd3..35c67d1f255 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -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.
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index 610ef1204e6..25d6f234198 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -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.
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 257277394f8..416f9e7286b 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -34,6 +34,14 @@ config MFD_ASIC3
This driver supports the ASIC3 multifunction chip found on many
PDAs (mainly iPAQ and HTC based ones)
+config MFD_DM355EVM_MSP
+ bool "DaVinci DM355 EVM microcontroller"
+ depends on I2C && MACH_DAVINCI_DM355_EVM
+ help
+ This driver supports the MSP430 microcontroller used on these
+ boards. MSP430 firmware manages resets and power sequencing,
+ inputs from buttons and the IR remote, LEDs, an RTC, and more.
+
config HTC_EGPIO
bool "HTC EGPIO support"
depends on GENERIC_HARDIRQS && GPIOLIB && ARM
@@ -61,9 +69,32 @@ config UCB1400_CORE
To compile this driver as a module, choose M here: the
module will be called ucb1400_core.
+config TPS65010
+ tristate "TPS6501x Power Management chips"
+ depends on I2C && GPIOLIB
+ default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
+ help
+ If you say yes here you get support for the TPS6501x series of
+ Power Management chips. These include voltage regulators,
+ lithium ion/polymer battery charging, and other features that
+ are often used in portable devices like cell phones and cameras.
+
+ This driver can also be built as a module. If so, the module
+ will be called tps65010.
+
+config MENELAUS
+ bool "Texas Instruments TWL92330/Menelaus PM chip"
+ depends on I2C=y && ARCH_OMAP24XX
+ help
+ If you say yes here you get support for the Texas Instruments
+ TWL92330/Menelaus Power Management chip. This include voltage
+ regulators, Dual slot memory card tranceivers, real-time clock
+ and other features that are often used in portable devices like
+ cell phones and PDAs.
+
config TWL4030_CORE
bool "Texas Instruments TWL4030/TPS659x0 Support"
- depends on I2C=y && GENERIC_HARDIRQS && (ARCH_OMAP2 || ARCH_OMAP3)
+ depends on I2C=y && GENERIC_HARDIRQS
help
Say yes here if you have TWL4030 family chip on your board.
This core driver provides register access and IRQ handling
@@ -116,6 +147,7 @@ config PMIC_DA903X
config MFD_WM8400
tristate "Support Wolfson Microelectronics WM8400"
+ select MFD_CORE
depends on I2C
help
Support for the Wolfson Microelecronics WM8400 PMIC and audio
@@ -142,6 +174,38 @@ config MFD_WM8350_CONFIG_MODE_3
bool
depends on MFD_WM8350
+config MFD_WM8351_CONFIG_MODE_0
+ bool
+ depends on MFD_WM8350
+
+config MFD_WM8351_CONFIG_MODE_1
+ bool
+ depends on MFD_WM8350
+
+config MFD_WM8351_CONFIG_MODE_2
+ bool
+ depends on MFD_WM8350
+
+config MFD_WM8351_CONFIG_MODE_3
+ bool
+ depends on MFD_WM8350
+
+config MFD_WM8352_CONFIG_MODE_0
+ bool
+ depends on MFD_WM8350
+
+config MFD_WM8352_CONFIG_MODE_1
+ bool
+ depends on MFD_WM8350
+
+config MFD_WM8352_CONFIG_MODE_2
+ bool
+ depends on MFD_WM8350
+
+config MFD_WM8352_CONFIG_MODE_3
+ bool
+ depends on MFD_WM8350
+
config MFD_WM8350_I2C
tristate "Support Wolfson Microelectronics WM8350 with I2C"
select MFD_WM8350
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 9a5ad8af911..0c9418b36c2 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -8,6 +8,8 @@ obj-$(CONFIG_MFD_ASIC3) += asic3.o
obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
+obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
+
obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o
obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o
obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o
@@ -17,6 +19,9 @@ wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
obj-$(CONFIG_MFD_WM8350) += wm8350.o
obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o
+obj-$(CONFIG_TPS65010) += tps65010.o
+obj-$(CONFIG_MENELAUS) += menelaus.o
+
obj-$(CONFIG_TWL4030_CORE) += twl4030-core.o twl4030-irq.o
obj-$(CONFIG_MFD_CORE) += mfd-core.o
@@ -31,4 +36,4 @@ obj-$(CONFIG_MCP_UCB1200) += ucb1x00-assabet.o
endif
obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o
-obj-$(CONFIG_PMIC_DA903X) += da903x.o \ No newline at end of file
+obj-$(CONFIG_PMIC_DA903X) += da903x.o
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c
index 0b5bd85dfce..99f8dcfe3d9 100644
--- a/drivers/mfd/da903x.c
+++ b/drivers/mfd/da903x.c
@@ -151,12 +151,24 @@ int da903x_write(struct device *dev, int reg, uint8_t val)
}
EXPORT_SYMBOL_GPL(da903x_write);
+int da903x_writes(struct device *dev, int reg, int len, uint8_t *val)
+{
+ return __da903x_writes(to_i2c_client(dev), reg, len, val);
+}
+EXPORT_SYMBOL_GPL(da903x_writes);
+
int da903x_read(struct device *dev, int reg, uint8_t *val)
{
return __da903x_read(to_i2c_client(dev), reg, val);
}
EXPORT_SYMBOL_GPL(da903x_read);
+int da903x_reads(struct device *dev, int reg, int len, uint8_t *val)
+{
+ return __da903x_reads(to_i2c_client(dev), reg, len, val);
+}
+EXPORT_SYMBOL_GPL(da903x_reads);
+
int da903x_set_bits(struct device *dev, int reg, uint8_t bit_mask)
{
struct da903x_chip *chip = dev_get_drvdata(dev);
@@ -435,13 +447,13 @@ static const struct i2c_device_id da903x_id_table[] = {
};
MODULE_DEVICE_TABLE(i2c, da903x_id_table);
-static int __devexit __remove_subdev(struct device *dev, void *unused)
+static int __remove_subdev(struct device *dev, void *unused)
{
platform_device_unregister(to_platform_device(dev));
return 0;
}
-static int __devexit da903x_remove_subdevs(struct da903x_chip *chip)
+static int da903x_remove_subdevs(struct da903x_chip *chip)
{
return device_for_each_child(chip->dev, NULL, __remove_subdev);
}
diff --git a/drivers/mfd/dm355evm_msp.c b/drivers/mfd/dm355evm_msp.c
new file mode 100644
index 00000000000..4214b3f7242
--- /dev/null
+++ b/drivers/mfd/dm355evm_msp.c
@@ -0,0 +1,420 @@
+/*
+ * dm355evm_msp.c - driver for MSP430 firmware on DM355EVM board
+ *
+ * Copyright (C) 2008 David Brownell
+ *
+ * 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/init.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/i2c.h>
+#include <linux/i2c/dm355evm_msp.h>
+
+
+/*
+ * The DM355 is a DaVinci chip with video support but no C64+ DSP. Its
+ * EVM board has an MSP430 programmed with firmware for various board
+ * support functions. This driver exposes some of them directly, and
+ * supports other drivers (e.g. RTC, input) for more complex access.
+ *
+ * Because this firmware is entirely board-specific, this file embeds
+ * knowledge that would be passed as platform_data in a generic driver.
+ *
+ * This driver was tested with firmware revision A4.
+ */
+
+#if defined(CONFIG_KEYBOARD_DM355EVM) \
+ || defined(CONFIG_KEYBOARD_DM355EVM_MODULE)
+#define msp_has_keyboard() true
+#else
+#define msp_has_keyboard() false
+#endif
+
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+#define msp_has_leds() true
+#else
+#define msp_has_leds() false
+#endif
+
+#if defined(CONFIG_RTC_DRV_DM355EVM) || defined(CONFIG_RTC_DRV_DM355EVM_MODULE)
+#define msp_has_rtc() true
+#else
+#define msp_has_rtc() false
+#endif
+
+#if defined(CONFIG_VIDEO_TVP514X) || defined(CONFIG_VIDEO_TVP514X_MODULE)
+#define msp_has_tvp() true
+#else
+#define msp_has_tvp() false
+#endif
+
+
+/*----------------------------------------------------------------------*/
+
+/* REVISIT for paranoia's sake, retry reads/writes on error */
+
+static struct i2c_client *msp430;
+
+/**
+ * dm355evm_msp_write - Writes a register in dm355evm_msp
+ * @value: the value to be written
+ * @reg: register address
+ *
+ * Returns result of operation - 0 is success, else negative errno
+ */
+int dm355evm_msp_write(u8 value, u8 reg)
+{
+ return i2c_smbus_write_byte_data(msp430, reg, value);
+}
+EXPORT_SYMBOL(dm355evm_msp_write);
+
+/**
+ * dm355evm_msp_read - Reads a register from dm355evm_msp
+ * @reg: register address
+ *
+ * Returns result of operation - value, or negative errno
+ */
+int dm355evm_msp_read(u8 reg)
+{
+ return i2c_smbus_read_byte_data(msp430, reg);
+}
+EXPORT_SYMBOL(dm355evm_msp_read);
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Many of the msp430 pins are just used as fixed-direction GPIOs.
+ * We could export a few more of them this way, if we wanted.
+ */
+#define MSP_GPIO(bit,reg) ((DM355EVM_MSP_ ## reg) << 3 | (bit))
+
+static const u8 msp_gpios[] = {
+ /* eight leds */
+ MSP_GPIO(0, LED), MSP_GPIO(1, LED),
+ MSP_GPIO(2, LED), MSP_GPIO(3, LED),
+ MSP_GPIO(4, LED), MSP_GPIO(5, LED),
+ MSP_GPIO(6, LED), MSP_GPIO(7, LED),
+ /* SW6 and the NTSC/nPAL jumper */
+ MSP_GPIO(0, SWITCH1), MSP_GPIO(1, SWITCH1),
+ MSP_GPIO(2, SWITCH1), MSP_GPIO(3, SWITCH1),
+ MSP_GPIO(4, SWITCH1),
+};
+
+#define MSP_GPIO_REG(offset) (msp_gpios[(offset)] >> 3)
+#define MSP_GPIO_MASK(offset) BIT(msp_gpios[(offset)] & 0x07)
+
+static int msp_gpio_in(struct gpio_chip *chip, unsigned offset)
+{
+ switch (MSP_GPIO_REG(offset)) {
+ case DM355EVM_MSP_SWITCH1:
+ case DM355EVM_MSP_SWITCH2:
+ case DM355EVM_MSP_SDMMC:
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static u8 msp_led_cache;
+
+static int msp_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ int reg, status;
+
+ reg = MSP_GPIO_REG(offset);
+ status = dm355evm_msp_read(reg);
+ if (status < 0)
+ return status;
+ if (reg == DM355EVM_MSP_LED)
+ msp_led_cache = status;
+ return status & MSP_GPIO_MASK(offset);
+}
+
+static int msp_gpio_out(struct gpio_chip *chip, unsigned offset, int value)
+{
+ int mask, bits;
+
+ /* NOTE: there are some other signals that could be
+ * packaged as output GPIOs, but they aren't as useful
+ * as the LEDs ... so for now we don't.
+ */
+ if (MSP_GPIO_REG(offset) != DM355EVM_MSP_LED)
+ return -EINVAL;
+
+ mask = MSP_GPIO_MASK(offset);
+ bits = msp_led_cache;
+
+ bits &= ~mask;
+ if (value)
+ bits |= mask;
+ msp_led_cache = bits;
+
+ return dm355evm_msp_write(bits, DM355EVM_MSP_LED);
+}
+
+static void msp_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ msp_gpio_out(chip, offset, value);
+}
+
+static struct gpio_chip dm355evm_msp_gpio = {
+ .label = "dm355evm_msp",
+ .owner = THIS_MODULE,
+ .direction_input = msp_gpio_in,
+ .get = msp_gpio_get,
+ .direction_output = msp_gpio_out,
+ .set = msp_gpio_set,
+ .base = -EINVAL, /* dynamic assignment */
+ .ngpio = ARRAY_SIZE(msp_gpios),
+ .can_sleep = true,
+};
+
+/*----------------------------------------------------------------------*/
+
+static struct device *add_child(struct i2c_client *client, const char *name,
+ void *pdata, unsigned pdata_len,
+ bool can_wakeup, int irq)
+{
+ struct platform_device *pdev;
+ int status;
+
+ pdev = platform_device_alloc(name, -1);
+ if (!pdev) {
+ dev_dbg(&client->dev, "can't alloc dev\n");
+ status = -ENOMEM;
+ goto err;
+ }
+
+ device_init_wakeup(&pdev->dev, can_wakeup);
+ pdev->dev.parent = &client->dev;
+
+ if (pdata) {
+ status = platform_device_add_data(pdev, pdata, pdata_len);
+ if (status < 0) {
+ dev_dbg(&pdev->dev, "can't add platform_data\n");
+ goto err;
+ }
+ }
+
+ if (irq) {
+ struct resource r = {
+ .start = irq,
+ .flags = IORESOURCE_IRQ,
+ };
+
+ status = platform_device_add_resources(pdev, &r, 1);
+ if (status < 0) {
+ dev_dbg(&pdev->dev, "can't add irq\n");
+ goto err;
+ }
+ }
+
+ status = platform_device_add(pdev);
+
+err:
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_err(&client->dev, "can't add %s dev\n", name);
+ return ERR_PTR(status);
+ }
+ return &pdev->dev;
+}
+
+static int add_children(struct i2c_client *client)
+{
+ static const struct {
+ int offset;
+ char *label;
+ } config_inputs[] = {
+ /* 8 == right after the LEDs */
+ { 8 + 0, "sw6_1", },
+ { 8 + 1, "sw6_2", },
+ { 8 + 2, "sw6_3", },
+ { 8 + 3, "sw6_4", },
+ { 8 + 4, "NTSC/nPAL", },
+ };
+
+ struct device *child;
+ int status;
+ int i;
+
+ /* GPIO-ish stuff */
+ dm355evm_msp_gpio.dev = &client->dev;
+ status = gpiochip_add(&dm355evm_msp_gpio);
+ if (status < 0)
+ return status;
+
+ /* LED output */
+ if (msp_has_leds()) {
+#define GPIO_LED(l) .name = l, .active_low = true
+ static struct gpio_led evm_leds[] = {
+ { GPIO_LED("dm355evm::ds14"),
+ .default_trigger = "heartbeat", },
+ { GPIO_LED("dm355evm::ds15"),
+ .default_trigger = "mmc0", },
+ { GPIO_LED("dm355evm::ds16"),
+ /* could also be a CE-ATA drive */
+ .default_trigger = "mmc1", },
+ { GPIO_LED("dm355evm::ds17"),
+ .default_trigger = "nand-disk", },
+ { GPIO_LED("dm355evm::ds18"), },
+ { GPIO_LED("dm355evm::ds19"), },
+ { GPIO_LED("dm355evm::ds20"), },
+ { GPIO_LED("dm355evm::ds21"), },
+ };
+#undef GPIO_LED
+
+ struct gpio_led_platform_data evm_led_data = {
+ .num_leds = ARRAY_SIZE(evm_leds),
+ .leds = evm_leds,
+ };
+
+ for (i = 0; i < ARRAY_SIZE(evm_leds); i++)
+ evm_leds[i].gpio = i + dm355evm_msp_gpio.base;
+
+ /* NOTE: these are the only fully programmable LEDs
+ * on the board, since GPIO-61/ds22 (and many signals
+ * going to DC7) must be used for AEMIF address lines
+ * unless the top 1 GB of NAND is unused...
+ */
+ child = add_child(client, "leds-gpio",
+ &evm_led_data, sizeof(evm_led_data),
+ false, 0);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+ }
+
+ /* configuration inputs */
+ for (i = 0; i < ARRAY_SIZE(config_inputs); i++) {
+ int gpio = dm355evm_msp_gpio.base + config_inputs[i].offset;
+
+ gpio_request(gpio, config_inputs[i].label);
+ gpio_direction_input(gpio);
+
+ /* make it easy for userspace to see these */
+ gpio_export(gpio, false);
+ }
+
+ /* RTC is a 32 bit counter, no alarm */
+ if (msp_has_rtc()) {
+ child = add_child(client, "rtc-dm355evm",
+ NULL, 0, false, 0);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+ }
+
+ /* input from buttons and IR remote (uses the IRQ) */
+ if (msp_has_keyboard()) {
+ child = add_child(client, "dm355evm_keys",
+ NULL, 0, true, client->irq);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+ }
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------*/
+
+static void dm355evm_command(unsigned command)
+{
+ int status;
+
+ status = dm355evm_msp_write(command, DM355EVM_MSP_COMMAND);
+ if (status < 0)
+ dev_err(&msp430->dev, "command %d failure %d\n",
+ command, status);
+}
+
+static void dm355evm_power_off(void)
+{
+ dm355evm_command(MSP_COMMAND_POWEROFF);
+}
+
+static int dm355evm_msp_remove(struct i2c_client *client)
+{
+ pm_power_off = NULL;
+ msp430 = NULL;
+ return 0;
+}
+
+static int
+dm355evm_msp_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ int status;
+ const char *video = msp_has_tvp() ? "TVP5146" : "imager";
+
+ if (msp430)
+ return -EBUSY;
+ msp430 = client;
+
+ /* display revision status; doubles as sanity check */
+ status = dm355evm_msp_read(DM355EVM_MSP_FIRMREV);
+ if (status < 0)
+ goto fail;
+ dev_info(&client->dev, "firmware v.%02X, %s as video-in\n",
+ status, video);
+
+ /* mux video input: either tvp5146 or some external imager */
+ status = dm355evm_msp_write(msp_has_tvp() ? 0 : MSP_VIDEO_IMAGER,
+ DM355EVM_MSP_VIDEO_IN);
+ if (status < 0)
+ dev_warn(&client->dev, "error %d muxing %s as video-in\n",
+ status, video);
+
+ /* init LED cache, and turn off the LEDs */
+ msp_led_cache = 0xff;
+ dm355evm_msp_write(msp_led_cache, DM355EVM_MSP_LED);
+
+ /* export capabilities we support */
+ status = add_children(client);
+ if (status < 0)
+ goto fail;
+
+ /* PM hookup */
+ pm_power_off = dm355evm_power_off;
+
+ return 0;
+
+fail:
+ /* FIXME remove children ... */
+ dm355evm_msp_remove(client);
+ return status;
+}
+
+static const struct i2c_device_id dm355evm_msp_ids[] = {
+ { "dm355evm_msp", 0 },
+ { /* end of list */ },
+};
+MODULE_DEVICE_TABLE(i2c, dm355evm_msp_ids);
+
+static struct i2c_driver dm355evm_msp_driver = {
+ .driver.name = "dm355evm_msp",
+ .id_table = dm355evm_msp_ids,
+ .probe = dm355evm_msp_probe,
+ .remove = dm355evm_msp_remove,
+};
+
+static int __init dm355evm_msp_init(void)
+{
+ return i2c_add_driver(&dm355evm_msp_driver);
+}
+subsys_initcall(dm355evm_msp_init);
+
+static void __exit dm355evm_msp_exit(void)
+{
+ i2c_del_driver(&dm355evm_msp_driver);
+}
+module_exit(dm355evm_msp_exit);
+
+MODULE_DESCRIPTION("Interface to MSP430 firmware on DM355EVM");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/chips/menelaus.c b/drivers/mfd/menelaus.c
index 4b364bae6b3..4b364bae6b3 100644
--- a/drivers/i2c/chips/menelaus.c
+++ b/drivers/mfd/menelaus.c
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 6c0d1bec4b7..54ddf3772e0 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -34,6 +34,7 @@ static int mfd_add_device(struct device *parent, int id,
goto fail_device;
pdev->dev.parent = parent;
+ platform_set_drvdata(pdev, cell->driver_data);
ret = platform_device_add_data(pdev,
cell->platform_data, cell->data_size);
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/mfd/tps65010.c
index acf8b9d5f57..acf8b9d5f57 100644
--- a/drivers/i2c/chips/tps65010.c
+++ b/drivers/mfd/tps65010.c
diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl4030-core.c
index dd843c4fbcc..b59c385cbc1 100644
--- a/drivers/mfd/twl4030-core.c
+++ b/drivers/mfd/twl4030-core.c
@@ -33,6 +33,8 @@
#include <linux/clk.h>
#include <linux/err.h>
+#include <linux/regulator/machine.h>
+
#include <linux/i2c.h>
#include <linux/i2c/twl4030.h>
@@ -71,6 +73,13 @@
#define twl_has_gpio() false
#endif
+#if defined(CONFIG_REGULATOR_TWL4030) \
+ || defined(CONFIG_REGULATOR_TWL4030_MODULE)
+#define twl_has_regulator() true
+#else
+#define twl_has_regulator() false
+#endif
+
#if defined(CONFIG_TWL4030_MADC) || defined(CONFIG_TWL4030_MADC_MODULE)
#define twl_has_madc() true
#else
@@ -149,6 +158,10 @@
#define HIGH_PERF_SQ (1 << 3)
+/* chip-specific feature flags, for i2c_device_id.driver_data */
+#define TWL4030_VAUX2 BIT(0) /* pre-5030 voltage ranges */
+#define TPS_SUBSET BIT(1) /* tps659[23]0 have fewer LDOs */
+
/*----------------------------------------------------------------------*/
/* is driver active, bound to a chip? */
@@ -225,7 +238,7 @@ static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = {
*
* Returns the result of operation - 0 is success
*/
-int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, u8 num_bytes)
+int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
{
int ret;
int sid;
@@ -274,7 +287,7 @@ EXPORT_SYMBOL(twl4030_i2c_write);
*
* Returns result of operation - num_bytes is success else failure.
*/
-int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, u8 num_bytes)
+int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
{
int ret;
u8 val;
@@ -352,258 +365,258 @@ EXPORT_SYMBOL(twl4030_i2c_read_u8);
/*----------------------------------------------------------------------*/
-/*
- * NOTE: We know the first 8 IRQs after pdata->base_irq are
- * for the PIH, and the next are for the PWR_INT SIH, since
- * that's how twl_init_irq() sets things up.
- */
-
-static int add_children(struct twl4030_platform_data *pdata)
+static struct device *
+add_numbered_child(unsigned chip, const char *name, int num,
+ void *pdata, unsigned pdata_len,
+ bool can_wakeup, int irq0, int irq1)
{
- struct platform_device *pdev = NULL;
- struct twl4030_client *twl = NULL;
- int status = 0;
+ struct platform_device *pdev;
+ struct twl4030_client *twl = &twl4030_modules[chip];
+ int status;
+
+ pdev = platform_device_alloc(name, num);
+ if (!pdev) {
+ dev_dbg(&twl->client->dev, "can't alloc dev\n");
+ status = -ENOMEM;
+ goto err;
+ }
- if (twl_has_bci() && pdata->bci) {
- twl = &twl4030_modules[3];
+ device_init_wakeup(&pdev->dev, can_wakeup);
+ pdev->dev.parent = &twl->client->dev;
- pdev = platform_device_alloc("twl4030_bci", -1);
- if (!pdev) {
- pr_debug("%s: can't alloc bci dev\n", DRIVER_NAME);
- status = -ENOMEM;
+ if (pdata) {
+ status = platform_device_add_data(pdev, pdata, pdata_len);
+ if (status < 0) {
+ dev_dbg(&pdev->dev, "can't add platform_data\n");
goto err;
}
+ }
- if (status == 0) {
- pdev->dev.parent = &twl->client->dev;
- status = platform_device_add_data(pdev, pdata->bci,
- sizeof(*pdata->bci));
- if (status < 0) {
- dev_dbg(&twl->client->dev,
- "can't add bci data, %d\n",
- status);
- goto err;
- }
- }
-
- if (status == 0) {
- struct resource r = {
- .start = pdata->irq_base + 8 + 1,
- .flags = IORESOURCE_IRQ,
- };
-
- status = platform_device_add_resources(pdev, &r, 1);
- }
-
- if (status == 0)
- status = platform_device_add(pdev);
+ if (irq0) {
+ struct resource r[2] = {
+ { .start = irq0, .flags = IORESOURCE_IRQ, },
+ { .start = irq1, .flags = IORESOURCE_IRQ, },
+ };
+ status = platform_device_add_resources(pdev, r, irq1 ? 2 : 1);
if (status < 0) {
- platform_device_put(pdev);
- dev_dbg(&twl->client->dev,
- "can't create bci dev, %d\n",
- status);
+ dev_dbg(&pdev->dev, "can't add irqs\n");
goto err;
}
}
- if (twl_has_gpio() && pdata->gpio) {
- twl = &twl4030_modules[1];
+ status = platform_device_add(pdev);
- pdev = platform_device_alloc("twl4030_gpio", -1);
- if (!pdev) {
- pr_debug("%s: can't alloc gpio dev\n", DRIVER_NAME);
- status = -ENOMEM;
- goto err;
- }
+err:
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_err(&twl->client->dev, "can't add %s dev\n", name);
+ return ERR_PTR(status);
+ }
+ return &pdev->dev;
+}
- /* more driver model init */
- if (status == 0) {
- pdev->dev.parent = &twl->client->dev;
- /* device_init_wakeup(&pdev->dev, 1); */
-
- status = platform_device_add_data(pdev, pdata->gpio,
- sizeof(*pdata->gpio));
- if (status < 0) {
- dev_dbg(&twl->client->dev,
- "can't add gpio data, %d\n",
- status);
- goto err;
- }
- }
+static inline struct device *add_child(unsigned chip, const char *name,
+ void *pdata, unsigned pdata_len,
+ bool can_wakeup, int irq0, int irq1)
+{
+ return add_numbered_child(chip, name, -1, pdata, pdata_len,
+ can_wakeup, irq0, irq1);
+}
- /* GPIO module IRQ */
- if (status == 0) {
- struct resource r = {
- .start = pdata->irq_base + 0,
- .flags = IORESOURCE_IRQ,
- };
+static struct device *
+add_regulator_linked(int num, struct regulator_init_data *pdata,
+ struct regulator_consumer_supply *consumers,
+ unsigned num_consumers)
+{
+ /* regulator framework demands init_data ... */
+ if (!pdata)
+ return NULL;
- status = platform_device_add_resources(pdev, &r, 1);
- }
+ if (consumers) {
+ pdata->consumer_supplies = consumers;
+ pdata->num_consumer_supplies = num_consumers;
+ }
- if (status == 0)
- status = platform_device_add(pdev);
+ /* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */
+ return add_numbered_child(3, "twl4030_reg", num,
+ pdata, sizeof(*pdata), false, 0, 0);
+}
- if (status < 0) {
- platform_device_put(pdev);
- dev_dbg(&twl->client->dev,
- "can't create gpio dev, %d\n",
- status);
- goto err;
- }
+static struct device *
+add_regulator(int num, struct regulator_init_data *pdata)
+{
+ return add_regulator_linked(num, pdata, NULL, 0);
+}
+
+/*
+ * NOTE: We know the first 8 IRQs after pdata->base_irq are
+ * for the PIH, and the next are for the PWR_INT SIH, since
+ * that's how twl_init_irq() sets things up.
+ */
+
+static int
+add_children(struct twl4030_platform_data *pdata, unsigned long features)
+{
+ struct device *child;
+ struct device *usb_transceiver = NULL;
+
+ if (twl_has_bci() && pdata->bci && !(features & TPS_SUBSET)) {
+ child = add_child(3, "twl4030_bci",
+ pdata->bci, sizeof(*pdata->bci),
+ false,
+ /* irq0 = CHG_PRES, irq1 = BCI */
+ pdata->irq_base + 8 + 1, pdata->irq_base + 2);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+ }
+
+ if (twl_has_gpio() && pdata->gpio) {
+ child = add_child(1, "twl4030_gpio",
+ pdata->gpio, sizeof(*pdata->gpio),
+ false, pdata->irq_base + 0, 0);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
}
if (twl_has_keypad() && pdata->keypad) {
- pdev = platform_device_alloc("twl4030_keypad", -1);
- if (pdev) {
- twl = &twl4030_modules[2];
- pdev->dev.parent = &twl->client->dev;
- device_init_wakeup(&pdev->dev, 1);
- status = platform_device_add_data(pdev, pdata->keypad,
- sizeof(*pdata->keypad));
- if (status < 0) {
- dev_dbg(&twl->client->dev,
- "can't add keypad data, %d\n",
- status);
- platform_device_put(pdev);
- goto err;
- }
- status = platform_device_add(pdev);
- if (status < 0) {
- platform_device_put(pdev);
- dev_dbg(&twl->client->dev,
- "can't create keypad dev, %d\n",
- status);
- goto err;
- }
- } else {
- pr_debug("%s: can't alloc keypad dev\n", DRIVER_NAME);
- status = -ENOMEM;
- goto err;
- }
+ child = add_child(2, "twl4030_keypad",
+ pdata->keypad, sizeof(*pdata->keypad),
+ true, pdata->irq_base + 1, 0);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
}
if (twl_has_madc() && pdata->madc) {
- pdev = platform_device_alloc("twl4030_madc", -1);
- if (pdev) {
- twl = &twl4030_modules[2];
- pdev->dev.parent = &twl->client->dev;
- device_init_wakeup(&pdev->dev, 1);
- status = platform_device_add_data(pdev, pdata->madc,
- sizeof(*pdata->madc));
- if (status < 0) {
- platform_device_put(pdev);
- dev_dbg(&twl->client->dev,
- "can't add madc data, %d\n",
- status);
- goto err;
- }
- status = platform_device_add(pdev);
- if (status < 0) {
- platform_device_put(pdev);
- dev_dbg(&twl->client->dev,
- "can't create madc dev, %d\n",
- status);
- goto err;
- }
- } else {
- pr_debug("%s: can't alloc madc dev\n", DRIVER_NAME);
- status = -ENOMEM;
- goto err;
- }
+ child = add_child(2, "twl4030_madc",
+ pdata->madc, sizeof(*pdata->madc),
+ true, pdata->irq_base + 3, 0);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
}
if (twl_has_rtc()) {
- twl = &twl4030_modules[3];
-
- pdev = platform_device_alloc("twl4030_rtc", -1);
- if (!pdev) {
- pr_debug("%s: can't alloc rtc dev\n", DRIVER_NAME);
- status = -ENOMEM;
- } else {
- pdev->dev.parent = &twl->client->dev;
- device_init_wakeup(&pdev->dev, 1);
- }
-
/*
- * REVISIT platform_data here currently might use of
+ * REVISIT platform_data here currently might expose the
* "msecure" line ... but for now we just expect board
- * setup to tell the chip "we are secure" at all times.
+ * setup to tell the chip "it's always ok to SET_TIME".
* Eventually, Linux might become more aware of such
* HW security concerns, and "least privilege".
*/
-
- /* RTC module IRQ */
- if (status == 0) {
- struct resource r = {
- .start = pdata->irq_base + 8 + 3,
- .flags = IORESOURCE_IRQ,
- };
-
- status = platform_device_add_resources(pdev, &r, 1);
- }
-
- if (status == 0)
- status = platform_device_add(pdev);
-
- if (status < 0) {
- platform_device_put(pdev);
- dev_dbg(&twl->client->dev,
- "can't create rtc dev, %d\n",
- status);
- goto err;
- }
+ child = add_child(3, "twl4030_rtc",
+ NULL, 0,
+ true, pdata->irq_base + 8 + 3, 0);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
}
if (twl_has_usb() && pdata->usb) {
- twl = &twl4030_modules[0];
-
- pdev = platform_device_alloc("twl4030_usb", -1);
- if (!pdev) {
- pr_debug("%s: can't alloc usb dev\n", DRIVER_NAME);
- status = -ENOMEM;
- goto err;
- }
-
- if (status == 0) {
- pdev->dev.parent = &twl->client->dev;
- device_init_wakeup(&pdev->dev, 1);
- status = platform_device_add_data(pdev, pdata->usb,
- sizeof(*pdata->usb));
- if (status < 0) {
- platform_device_put(pdev);
- dev_dbg(&twl->client->dev,
- "can't add usb data, %d\n",
- status);
- goto err;
- }
- }
-
- if (status == 0) {
- struct resource r = {
- .start = pdata->irq_base + 8 + 2,
- .flags = IORESOURCE_IRQ,
- };
+ child = add_child(0, "twl4030_usb",
+ pdata->usb, sizeof(*pdata->usb),
+ true,
+ /* irq0 = USB_PRES, irq1 = USB */
+ pdata->irq_base + 8 + 2, pdata->irq_base + 4);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ /* we need to connect regulators to this transceiver */
+ usb_transceiver = child;
+ }
- status = platform_device_add_resources(pdev, &r, 1);
- }
+ if (twl_has_regulator()) {
+ /*
+ child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+ */
+
+ child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator(TWL4030_REG_VDAC, pdata->vdac);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator((features & TWL4030_VAUX2)
+ ? TWL4030_REG_VAUX2_4030
+ : TWL4030_REG_VAUX2,
+ pdata->vaux2);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+ }
- if (status == 0)
- status = platform_device_add(pdev);
+ if (twl_has_regulator() && usb_transceiver) {
+ static struct regulator_consumer_supply usb1v5 = {
+ .supply = "usb1v5",
+ };
+ static struct regulator_consumer_supply usb1v8 = {
+ .supply = "usb1v8",
+ };
+ static struct regulator_consumer_supply usb3v1 = {
+ .supply = "usb3v1",
+ };
+
+ /* this is a template that gets copied */
+ struct regulator_init_data usb_fixed = {
+ .constraints.valid_modes_mask =
+ REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .constraints.valid_ops_mask =
+ REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ };
+
+ usb1v5.dev = usb_transceiver;
+ usb1v8.dev = usb_transceiver;
+ usb3v1.dev = usb_transceiver;
+
+ child = add_regulator_linked(TWL4030_REG_VUSB1V5, &usb_fixed,
+ &usb1v5, 1);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator_linked(TWL4030_REG_VUSB1V8, &usb_fixed,
+ &usb1v8, 1);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator_linked(TWL4030_REG_VUSB3V1, &usb_fixed,
+ &usb3v1, 1);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+ }
- if (status < 0) {
- platform_device_put(pdev);
- dev_dbg(&twl->client->dev,
- "can't create usb dev, %d\n",
- status);
- }
+ /* maybe add LDOs that are omitted on cost-reduced parts */
+ if (twl_has_regulator() && !(features & TPS_SUBSET)) {
+ /*
+ child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+ */
+
+ child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator(TWL4030_REG_VSIM, pdata->vsim);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
}
-err:
- if (status)
- pr_err("failed to add twl4030's children (status %d)\n", status);
- return status;
+ return 0;
}
/*----------------------------------------------------------------------*/
@@ -645,12 +658,7 @@ static void __init clocks_init(void)
osc = clk_get(NULL, "osc_ck");
else
osc = clk_get(NULL, "osc_sys_ck");
-#else
- /* REVISIT for non-OMAP systems, pass the clock rate from
- * board init code, using platform_data.
- */
- osc = ERR_PTR(-EIO);
-#endif
+
if (IS_ERR(osc)) {
printk(KERN_WARNING "Skipping twl4030 internal clock init and "
"using bootloader value (unknown osc rate)\n");
@@ -660,6 +668,18 @@ static void __init clocks_init(void)
rate = clk_get_rate(osc);
clk_put(osc);
+#else
+ /* REVISIT for non-OMAP systems, pass the clock rate from
+ * board init code, using platform_data.
+ */
+ osc = ERR_PTR(-EIO);
+
+ printk(KERN_WARNING "Skipping twl4030 internal clock init and "
+ "using bootloader value (unknown osc rate)\n");
+
+ return;
+#endif
+
switch (rate) {
case 19200000:
ctrl = HFCLK_FREQ_19p2_MHZ;
@@ -764,7 +784,7 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id)
goto fail;
}
- status = add_children(pdata);
+ status = add_children(pdata, id->driver_data);
fail:
if (status < 0)
twl4030_remove(client);
@@ -772,11 +792,11 @@ fail:
}
static const struct i2c_device_id twl4030_ids[] = {
- { "twl4030", 0 }, /* "Triton 2" */
- { "tps65950", 0 }, /* catalog version of twl4030 */
- { "tps65930", 0 }, /* fewer LDOs and DACs; no charger */
- { "tps65920", 0 }, /* fewer LDOs; no codec or charger */
- { "twl5030", 0 }, /* T2 updated */
+ { "twl4030", TWL4030_VAUX2 }, /* "Triton 2" */
+ { "twl5030", 0 }, /* T2 updated */
+ { "tps65950", 0 }, /* catalog version of twl5030 */
+ { "tps65930", TPS_SUBSET }, /* fewer LDOs and DACs; no charger */
+ { "tps65920", TPS_SUBSET }, /* fewer LDOs; no codec or charger */
{ /* end of list */ },
};
MODULE_DEVICE_TABLE(i2c, twl4030_ids);
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index fae868a8d49..b1087603698 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -180,10 +180,15 @@ static struct completion irq_event;
static int twl4030_irq_thread(void *data)
{
long irq = (long)data;
- irq_desc_t *desc = irq_desc + irq;
+ struct irq_desc *desc = irq_to_desc(irq);
static unsigned i2c_errors;
const static unsigned max_i2c_errors = 100;
+ if (!desc) {
+ pr_err("twl4030: Invalid IRQ: %ld\n", irq);
+ return -EINVAL;
+ }
+
current->flags |= PF_NOFREEZE;
while (!kthread_should_stop()) {
@@ -215,7 +220,13 @@ static int twl4030_irq_thread(void *data)
pih_isr;
pih_isr >>= 1, module_irq++) {
if (pih_isr & 0x1) {
- irq_desc_t *d = irq_desc + module_irq;
+ struct irq_desc *d = irq_to_desc(module_irq);
+
+ if (!d) {
+ pr_err("twl4030: Invalid SIH IRQ: %d\n",
+ module_irq);
+ return -EINVAL;
+ }
/* These can't be masked ... always warn
* if we get any surprises.
@@ -452,10 +463,16 @@ static void twl4030_sih_do_edge(struct work_struct *work)
/* Modify only the bits we know must change */
while (edge_change) {
int i = fls(edge_change) - 1;
- struct irq_desc *d = irq_desc + i + agent->irq_base;
+ struct irq_desc *d = irq_to_desc(i + agent->irq_base);
int byte = 1 + (i >> 2);
int off = (i & 0x3) * 2;
+ if (!d) {
+ pr_err("twl4030: Invalid IRQ: %d\n",
+ i + agent->irq_base);
+ return;
+ }
+
bytes[byte] &= ~(0x03 << off);
spin_lock_irq(&d->lock);
@@ -512,9 +529,14 @@ static void twl4030_sih_unmask(unsigned irq)
static int twl4030_sih_set_type(unsigned irq, unsigned trigger)
{
struct sih_agent *sih = get_irq_chip_data(irq);
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = irq_to_desc(irq);
unsigned long flags;
+ if (!desc) {
+ pr_err("twl4030: Invalid IRQ: %d\n", irq);
+ return -EINVAL;
+ }
+
if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
return -EINVAL;
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c
index 0d47fb9e4b3..3a273ccef3f 100644
--- a/drivers/mfd/wm8350-core.c
+++ b/drivers/mfd/wm8350-core.c
@@ -63,7 +63,6 @@
*/
static DEFINE_MUTEX(io_mutex);
static DEFINE_MUTEX(reg_lock_mutex);
-static DEFINE_MUTEX(auxadc_mutex);
/* Perform a physical read from the device.
*/
@@ -299,6 +298,13 @@ int wm8350_block_write(struct wm8350 *wm8350, int start_reg, int regs,
}
EXPORT_SYMBOL_GPL(wm8350_block_write);
+/**
+ * wm8350_reg_lock()
+ *
+ * The WM8350 has a hardware lock which can be used to prevent writes to
+ * some registers (generally those which can cause particularly serious
+ * problems if misused). This function enables that lock.
+ */
int wm8350_reg_lock(struct wm8350 *wm8350)
{
u16 key = WM8350_LOCK_KEY;
@@ -314,6 +320,15 @@ int wm8350_reg_lock(struct wm8350 *wm8350)
}
EXPORT_SYMBOL_GPL(wm8350_reg_lock);
+/**
+ * wm8350_reg_unlock()
+ *
+ * The WM8350 has a hardware lock which can be used to prevent writes to
+ * some registers (generally those which can cause particularly serious
+ * problems if misused). This function disables that lock so updates
+ * can be performed. For maximum safety this should be done only when
+ * required.
+ */
int wm8350_reg_unlock(struct wm8350 *wm8350)
{
u16 key = WM8350_UNLOCK_KEY;
@@ -1066,38 +1081,158 @@ int wm8350_unmask_irq(struct wm8350 *wm8350, int irq)
}
EXPORT_SYMBOL_GPL(wm8350_unmask_irq);
+int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref)
+{
+ u16 reg, result = 0;
+ int tries = 5;
+
+ if (channel < WM8350_AUXADC_AUX1 || channel > WM8350_AUXADC_TEMP)
+ return -EINVAL;
+ if (channel >= WM8350_AUXADC_USB && channel <= WM8350_AUXADC_TEMP
+ && (scale != 0 || vref != 0))
+ return -EINVAL;
+
+ mutex_lock(&wm8350->auxadc_mutex);
+
+ /* Turn on the ADC */
+ reg = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_5);
+ wm8350_reg_write(wm8350, WM8350_POWER_MGMT_5, reg | WM8350_AUXADC_ENA);
+
+ if (scale || vref) {
+ reg = scale << 13;
+ reg |= vref << 12;
+ wm8350_reg_write(wm8350, WM8350_AUX1_READBACK + channel, reg);
+ }
+
+ reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1);
+ reg |= 1 << channel | WM8350_AUXADC_POLL;
+ wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_1, reg);
+
+ do {
+ schedule_timeout_interruptible(1);
+ reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1);
+ } while (tries-- && (reg & WM8350_AUXADC_POLL));
+
+ if (!tries)
+ dev_err(wm8350->dev, "adc chn %d read timeout\n", channel);
+ else
+ result = wm8350_reg_read(wm8350,
+ WM8350_AUX1_READBACK + channel);
+
+ /* Turn off the ADC */
+ reg = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_5);
+ wm8350_reg_write(wm8350, WM8350_POWER_MGMT_5,
+ reg & ~WM8350_AUXADC_ENA);
+
+ mutex_unlock(&wm8350->auxadc_mutex);
+
+ return result & WM8350_AUXADC_DATA1_MASK;
+}
+EXPORT_SYMBOL_GPL(wm8350_read_auxadc);
+
/*
* Cache is always host endian.
*/
-static int wm8350_create_cache(struct wm8350 *wm8350, int mode)
+static int wm8350_create_cache(struct wm8350 *wm8350, int type, int mode)
{
int i, ret = 0;
u16 value;
const u16 *reg_map;
- switch (mode) {
-#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_0
+ switch (type) {
case 0:
- reg_map = wm8350_mode0_defaults;
- break;
+ switch (mode) {
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_0
+ case 0:
+ reg_map = wm8350_mode0_defaults;
+ break;
#endif
#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_1
- case 1:
- reg_map = wm8350_mode1_defaults;
- break;
+ case 1:
+ reg_map = wm8350_mode1_defaults;
+ break;
#endif
#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_2
- case 2:
- reg_map = wm8350_mode2_defaults;
- break;
+ case 2:
+ reg_map = wm8350_mode2_defaults;
+ break;
#endif
#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_3
- case 3:
- reg_map = wm8350_mode3_defaults;
+ case 3:
+ reg_map = wm8350_mode3_defaults;
+ break;
+#endif
+ default:
+ dev_err(wm8350->dev,
+ "WM8350 configuration mode %d not supported\n",
+ mode);
+ return -EINVAL;
+ }
+ break;
+
+ case 1:
+ switch (mode) {
+#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_0
+ case 0:
+ reg_map = wm8351_mode0_defaults;
+ break;
+#endif
+#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_1
+ case 1:
+ reg_map = wm8351_mode1_defaults;
+ break;
+#endif
+#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_2
+ case 2:
+ reg_map = wm8351_mode2_defaults;
+ break;
+#endif
+#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_3
+ case 3:
+ reg_map = wm8351_mode3_defaults;
+ break;
+#endif
+ default:
+ dev_err(wm8350->dev,
+ "WM8351 configuration mode %d not supported\n",
+ mode);
+ return -EINVAL;
+ }
break;
+
+ case 2:
+ switch (mode) {
+#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_0
+ case 0:
+ reg_map = wm8352_mode0_defaults;
+ break;
+#endif
+#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_1
+ case 1:
+ reg_map = wm8352_mode1_defaults;
+ break;
#endif
+#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_2
+ case 2:
+ reg_map = wm8352_mode2_defaults;
+ break;
+#endif
+#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_3
+ case 3:
+ reg_map = wm8352_mode3_defaults;
+ break;
+#endif
+ default:
+ dev_err(wm8350->dev,
+ "WM8352 configuration mode %d not supported\n",
+ mode);
+ return -EINVAL;
+ }
+ break;
+
default:
- dev_err(wm8350->dev, "Configuration mode %d not supported\n",
+ dev_err(wm8350->dev,
+ "WM835x configuration mode %d not supported\n",
mode);
return -EINVAL;
}
@@ -1163,53 +1298,113 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
struct wm8350_platform_data *pdata)
{
int ret = -EINVAL;
- u16 id1, id2, mask, mode;
+ u16 id1, id2, mask_rev;
+ u16 cust_id, mode, chip_rev;
/* get WM8350 revision and config mode */
wm8350->read_dev(wm8350, WM8350_RESET_ID, sizeof(id1), &id1);
wm8350->read_dev(wm8350, WM8350_ID, sizeof(id2), &id2);
+ wm8350->read_dev(wm8350, WM8350_REVISION, sizeof(mask_rev), &mask_rev);
id1 = be16_to_cpu(id1);
id2 = be16_to_cpu(id2);
+ mask_rev = be16_to_cpu(mask_rev);
- if (id1 == 0x6143) {
- switch ((id2 & WM8350_CHIP_REV_MASK) >> 12) {
+ if (id1 != 0x6143) {
+ dev_err(wm8350->dev,
+ "Device with ID %x is not a WM8350\n", id1);
+ ret = -ENODEV;
+ goto err;
+ }
+
+ mode = id2 & WM8350_CONF_STS_MASK >> 10;
+ cust_id = id2 & WM8350_CUST_ID_MASK;
+ chip_rev = (id2 & WM8350_CHIP_REV_MASK) >> 12;
+ dev_info(wm8350->dev,
+ "CONF_STS %d, CUST_ID %d, MASK_REV %d, CHIP_REV %d\n",
+ mode, cust_id, mask_rev, chip_rev);
+
+ if (cust_id != 0) {
+ dev_err(wm8350->dev, "Unsupported CUST_ID\n");
+ ret = -ENODEV;
+ goto err;
+ }
+
+ switch (mask_rev) {
+ case 0:
+ wm8350->pmic.max_dcdc = WM8350_DCDC_6;
+ wm8350->pmic.max_isink = WM8350_ISINK_B;
+
+ switch (chip_rev) {
case WM8350_REV_E:
- dev_info(wm8350->dev, "Found Rev E device\n");
- wm8350->rev = WM8350_REV_E;
+ dev_info(wm8350->dev, "WM8350 Rev E\n");
break;
case WM8350_REV_F:
- dev_info(wm8350->dev, "Found Rev F device\n");
- wm8350->rev = WM8350_REV_F;
+ dev_info(wm8350->dev, "WM8350 Rev F\n");
break;
case WM8350_REV_G:
- dev_info(wm8350->dev, "Found Rev G device\n");
- wm8350->rev = WM8350_REV_G;
+ dev_info(wm8350->dev, "WM8350 Rev G\n");
+ wm8350->power.rev_g_coeff = 1;
+ break;
+ case WM8350_REV_H:
+ dev_info(wm8350->dev, "WM8350 Rev H\n");
+ wm8350->power.rev_g_coeff = 1;
break;
default:
/* For safety we refuse to run on unknown hardware */
- dev_info(wm8350->dev, "Found unknown rev\n");
+ dev_err(wm8350->dev, "Unknown WM8350 CHIP_REV\n");
ret = -ENODEV;
goto err;
}
- } else {
- dev_info(wm8350->dev, "Device with ID %x is not a WM8350\n",
- id1);
+ break;
+
+ case 1:
+ wm8350->pmic.max_dcdc = WM8350_DCDC_4;
+ wm8350->pmic.max_isink = WM8350_ISINK_A;
+
+ switch (chip_rev) {
+ case 0:
+ dev_info(wm8350->dev, "WM8351 Rev A\n");
+ wm8350->power.rev_g_coeff = 1;
+ break;
+
+ default:
+ dev_err(wm8350->dev, "Unknown WM8351 CHIP_REV\n");
+ ret = -ENODEV;
+ goto err;
+ }
+ break;
+
+ case 2:
+ wm8350->pmic.max_dcdc = WM8350_DCDC_6;
+ wm8350->pmic.max_isink = WM8350_ISINK_B;
+
+ switch (chip_rev) {
+ case 0:
+ dev_info(wm8350->dev, "WM8352 Rev A\n");
+ wm8350->power.rev_g_coeff = 1;
+ break;
+
+ default:
+ dev_err(wm8350->dev, "Unknown WM8352 CHIP_REV\n");
+ ret = -ENODEV;
+ goto err;
+ }
+ break;
+
+ default:
+ dev_err(wm8350->dev, "Unknown MASK_REV\n");
ret = -ENODEV;
goto err;
}
- mode = id2 & WM8350_CONF_STS_MASK >> 10;
- mask = id2 & WM8350_CUST_ID_MASK;
- dev_info(wm8350->dev, "Config mode %d, ROM mask %d\n", mode, mask);
-
- ret = wm8350_create_cache(wm8350, mode);
+ ret = wm8350_create_cache(wm8350, mask_rev, mode);
if (ret < 0) {
- printk(KERN_ERR "wm8350: failed to create register cache\n");
+ dev_err(wm8350->dev, "Failed to create register cache\n");
return ret;
}
- if (pdata->init) {
+ if (pdata && pdata->init) {
ret = pdata->init(wm8350);
if (ret != 0) {
dev_err(wm8350->dev, "Platform init() failed: %d\n",
@@ -1218,6 +1413,7 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
}
}
+ mutex_init(&wm8350->auxadc_mutex);
mutex_init(&wm8350->irq_mutex);
INIT_WORK(&wm8350->irq_work, wm8350_irq_worker);
if (irq) {
diff --git a/drivers/mfd/wm8350-i2c.c b/drivers/mfd/wm8350-i2c.c
index 3e0ce0e50ea..8d8c9321757 100644
--- a/drivers/mfd/wm8350-i2c.c
+++ b/drivers/mfd/wm8350-i2c.c
@@ -1,8 +1,6 @@
/*
* wm8350-i2c.c -- Generic I2C driver for Wolfson WM8350 PMIC
*
- * This driver defines and configures the WM8350 for the Freescale i.MX32ADS.
- *
* Copyright 2007, 2008 Wolfson Microelectronics PLC.
*
* Author: Liam Girdwood
@@ -99,6 +97,8 @@ static int wm8350_i2c_remove(struct i2c_client *i2c)
static const struct i2c_device_id wm8350_i2c_id[] = {
{ "wm8350", 0 },
+ { "wm8351", 0 },
+ { "wm8352", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8350_i2c_id);
diff --git a/drivers/mfd/wm8350-regmap.c b/drivers/mfd/wm8350-regmap.c
index 974678db22c..68887b817d1 100644
--- a/drivers/mfd/wm8350-regmap.c
+++ b/drivers/mfd/wm8350-regmap.c
@@ -1074,6 +1074,2102 @@ const u16 wm8350_mode3_defaults[] = {
};
#endif
+#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_0
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8351_mode0_defaults[] = {
+ 0x6143, /* R0 - Reset/ID */
+ 0x0000, /* R1 - ID */
+ 0x0001, /* R2 - Revision */
+ 0x1C02, /* R3 - System Control 1 */
+ 0x0004, /* R4 - System Control 2 */
+ 0x0000, /* R5 - System Hibernate */
+ 0x8A00, /* R6 - Interface Control */
+ 0x0000, /* R7 */
+ 0x8000, /* R8 - Power mgmt (1) */
+ 0x0000, /* R9 - Power mgmt (2) */
+ 0x0000, /* R10 - Power mgmt (3) */
+ 0x2000, /* R11 - Power mgmt (4) */
+ 0x0E00, /* R12 - Power mgmt (5) */
+ 0x0000, /* R13 - Power mgmt (6) */
+ 0x0000, /* R14 - Power mgmt (7) */
+ 0x0000, /* R15 */
+ 0x0000, /* R16 - RTC Seconds/Minutes */
+ 0x0100, /* R17 - RTC Hours/Day */
+ 0x0101, /* R18 - RTC Date/Month */
+ 0x1400, /* R19 - RTC Year */
+ 0x0000, /* R20 - Alarm Seconds/Minutes */
+ 0x0000, /* R21 - Alarm Hours/Day */
+ 0x0000, /* R22 - Alarm Date/Month */
+ 0x0320, /* R23 - RTC Time Control */
+ 0x0000, /* R24 - System Interrupts */
+ 0x0000, /* R25 - Interrupt Status 1 */
+ 0x0000, /* R26 - Interrupt Status 2 */
+ 0x0000, /* R27 */
+ 0x0000, /* R28 - Under Voltage Interrupt status */
+ 0x0000, /* R29 - Over Current Interrupt status */
+ 0x0000, /* R30 - GPIO Interrupt Status */
+ 0x0000, /* R31 - Comparator Interrupt Status */
+ 0x3FFF, /* R32 - System Interrupts Mask */
+ 0x0000, /* R33 - Interrupt Status 1 Mask */
+ 0x0000, /* R34 - Interrupt Status 2 Mask */
+ 0x0000, /* R35 */
+ 0x0000, /* R36 - Under Voltage Interrupt status Mask */
+ 0x0000, /* R37 - Over Current Interrupt status Mask */
+ 0x0000, /* R38 - GPIO Interrupt Status Mask */
+ 0x0000, /* R39 - Comparator Interrupt Status Mask */
+ 0x0040, /* R40 - Clock Control 1 */
+ 0x0000, /* R41 - Clock Control 2 */
+ 0x3A00, /* R42 - FLL Control 1 */
+ 0x7086, /* R43 - FLL Control 2 */
+ 0xC226, /* R44 - FLL Control 3 */
+ 0x0000, /* R45 - FLL Control 4 */
+ 0x0000, /* R46 */
+ 0x0000, /* R47 */
+ 0x0000, /* R48 - DAC Control */
+ 0x0000, /* R49 */
+ 0x00C0, /* R50 - DAC Digital Volume L */
+ 0x00C0, /* R51 - DAC Digital Volume R */
+ 0x0000, /* R52 */
+ 0x0040, /* R53 - DAC LR Rate */
+ 0x0000, /* R54 - DAC Clock Control */
+ 0x0000, /* R55 */
+ 0x0000, /* R56 */
+ 0x0000, /* R57 */
+ 0x4000, /* R58 - DAC Mute */
+ 0x0000, /* R59 - DAC Mute Volume */
+ 0x0000, /* R60 - DAC Side */
+ 0x0000, /* R61 */
+ 0x0000, /* R62 */
+ 0x0000, /* R63 */
+ 0x8000, /* R64 - ADC Control */
+ 0x0000, /* R65 */
+ 0x00C0, /* R66 - ADC Digital Volume L */
+ 0x00C0, /* R67 - ADC Digital Volume R */
+ 0x0000, /* R68 - ADC Divider */
+ 0x0000, /* R69 */
+ 0x0040, /* R70 - ADC LR Rate */
+ 0x0000, /* R71 */
+ 0x0303, /* R72 - Input Control */
+ 0x0000, /* R73 - IN3 Input Control */
+ 0x0000, /* R74 - Mic Bias Control */
+ 0x0000, /* R75 */
+ 0x0000, /* R76 - Output Control */
+ 0x0000, /* R77 - Jack Detect */
+ 0x0000, /* R78 - Anti Pop Control */
+ 0x0000, /* R79 */
+ 0x0040, /* R80 - Left Input Volume */
+ 0x0040, /* R81 - Right Input Volume */
+ 0x0000, /* R82 */
+ 0x0000, /* R83 */
+ 0x0000, /* R84 */
+ 0x0000, /* R85 */
+ 0x0000, /* R86 */
+ 0x0000, /* R87 */
+ 0x0800, /* R88 - Left Mixer Control */
+ 0x1000, /* R89 - Right Mixer Control */
+ 0x0000, /* R90 */
+ 0x0000, /* R91 */
+ 0x0000, /* R92 - OUT3 Mixer Control */
+ 0x0000, /* R93 - OUT4 Mixer Control */
+ 0x0000, /* R94 */
+ 0x0000, /* R95 */
+ 0x0000, /* R96 - Output Left Mixer Volume */
+ 0x0000, /* R97 - Output Right Mixer Volume */
+ 0x0000, /* R98 - Input Mixer Volume L */
+ 0x0000, /* R99 - Input Mixer Volume R */
+ 0x0000, /* R100 - Input Mixer Volume */
+ 0x0000, /* R101 */
+ 0x0000, /* R102 */
+ 0x0000, /* R103 */
+ 0x00E4, /* R104 - OUT1L Volume */
+ 0x00E4, /* R105 - OUT1R Volume */
+ 0x00E4, /* R106 - OUT2L Volume */
+ 0x02E4, /* R107 - OUT2R Volume */
+ 0x0000, /* R108 */
+ 0x0000, /* R109 */
+ 0x0000, /* R110 */
+ 0x0000, /* R111 - BEEP Volume */
+ 0x0A00, /* R112 - AI Formating */
+ 0x0000, /* R113 - ADC DAC COMP */
+ 0x0020, /* R114 - AI ADC Control */
+ 0x0020, /* R115 - AI DAC Control */
+ 0x0000, /* R116 */
+ 0x0000, /* R117 */
+ 0x0000, /* R118 */
+ 0x0000, /* R119 */
+ 0x0000, /* R120 */
+ 0x0000, /* R121 */
+ 0x0000, /* R122 */
+ 0x0000, /* R123 */
+ 0x0000, /* R124 */
+ 0x0000, /* R125 */
+ 0x0000, /* R126 */
+ 0x0000, /* R127 */
+ 0x1FFF, /* R128 - GPIO Debounce */
+ 0x0000, /* R129 - GPIO Pin pull up Control */
+ 0x0000, /* R130 - GPIO Pull down Control */
+ 0x0000, /* R131 - GPIO Interrupt Mode */
+ 0x0000, /* R132 */
+ 0x0000, /* R133 - GPIO Control */
+ 0x0FFC, /* R134 - GPIO Configuration (i/o) */
+ 0x0FFC, /* R135 - GPIO Pin Polarity / Type */
+ 0x0000, /* R136 */
+ 0x0000, /* R137 */
+ 0x0000, /* R138 */
+ 0x0000, /* R139 */
+ 0x0013, /* R140 - GPIO Function Select 1 */
+ 0x0000, /* R141 - GPIO Function Select 2 */
+ 0x0000, /* R142 - GPIO Function Select 3 */
+ 0x0003, /* R143 - GPIO Function Select 4 */
+ 0x0000, /* R144 - Digitiser Control (1) */
+ 0x0002, /* R145 - Digitiser Control (2) */
+ 0x0000, /* R146 */
+ 0x0000, /* R147 */
+ 0x0000, /* R148 */
+ 0x0000, /* R149 */
+ 0x0000, /* R150 */
+ 0x0000, /* R151 */
+ 0x7000, /* R152 - AUX1 Readback */
+ 0x7000, /* R153 - AUX2 Readback */
+ 0x7000, /* R154 - AUX3 Readback */
+ 0x7000, /* R155 - AUX4 Readback */
+ 0x0000, /* R156 - USB Voltage Readback */
+ 0x0000, /* R157 - LINE Voltage Readback */
+ 0x0000, /* R158 - BATT Voltage Readback */
+ 0x0000, /* R159 - Chip Temp Readback */
+ 0x0000, /* R160 */
+ 0x0000, /* R161 */
+ 0x0000, /* R162 */
+ 0x0000, /* R163 - Generic Comparator Control */
+ 0x0000, /* R164 - Generic comparator 1 */
+ 0x0000, /* R165 - Generic comparator 2 */
+ 0x0000, /* R166 - Generic comparator 3 */
+ 0x0000, /* R167 - Generic comparator 4 */
+ 0xA00F, /* R168 - Battery Charger Control 1 */
+ 0x0B06, /* R169 - Battery Charger Control 2 */
+ 0x0000, /* R170 - Battery Charger Control 3 */
+ 0x0000, /* R171 */
+ 0x0000, /* R172 - Current Sink Driver A */
+ 0x0000, /* R173 - CSA Flash control */
+ 0x0000, /* R174 */
+ 0x0000, /* R175 */
+ 0x0000, /* R176 - DCDC/LDO requested */
+ 0x032D, /* R177 - DCDC Active options */
+ 0x0000, /* R178 - DCDC Sleep options */
+ 0x0025, /* R179 - Power-check comparator */
+ 0x000E, /* R180 - DCDC1 Control */
+ 0x0000, /* R181 - DCDC1 Timeouts */
+ 0x1006, /* R182 - DCDC1 Low Power */
+ 0x0018, /* R183 - DCDC2 Control */
+ 0x0000, /* R184 - DCDC2 Timeouts */
+ 0x0000, /* R185 */
+ 0x0000, /* R186 - DCDC3 Control */
+ 0x0000, /* R187 - DCDC3 Timeouts */
+ 0x0006, /* R188 - DCDC3 Low Power */
+ 0x0000, /* R189 - DCDC4 Control */
+ 0x0000, /* R190 - DCDC4 Timeouts */
+ 0x0006, /* R191 - DCDC4 Low Power */
+ 0x0008, /* R192 */
+ 0x0000, /* R193 */
+ 0x0000, /* R194 */
+ 0x0000, /* R195 */
+ 0x0000, /* R196 */
+ 0x0006, /* R197 */
+ 0x0000, /* R198 */
+ 0x0003, /* R199 - Limit Switch Control */
+ 0x001C, /* R200 - LDO1 Control */
+ 0x0000, /* R201 - LDO1 Timeouts */
+ 0x001C, /* R202 - LDO1 Low Power */
+ 0x001B, /* R203 - LDO2 Control */
+ 0x0000, /* R204 - LDO2 Timeouts */
+ 0x001C, /* R205 - LDO2 Low Power */
+ 0x001B, /* R206 - LDO3 Control */
+ 0x0000, /* R207 - LDO3 Timeouts */
+ 0x001C, /* R208 - LDO3 Low Power */
+ 0x001B, /* R209 - LDO4 Control */
+ 0x0000, /* R210 - LDO4 Timeouts */
+ 0x001C, /* R211 - LDO4 Low Power */
+ 0x0000, /* R212 */
+ 0x0000, /* R213 */
+ 0x0000, /* R214 */
+ 0x0000, /* R215 - VCC_FAULT Masks */
+ 0x001F, /* R216 - Main Bandgap Control */
+ 0x0000, /* R217 - OSC Control */
+ 0x9000, /* R218 - RTC Tick Control */
+ 0x0000, /* R219 - Security1 */
+ 0x4000, /* R220 */
+ 0x0000, /* R221 */
+ 0x0000, /* R222 */
+ 0x0000, /* R223 */
+ 0x0000, /* R224 - Signal overrides */
+ 0x0000, /* R225 - DCDC/LDO status */
+ 0x0000, /* R226 - Charger Overides/status */
+ 0x0000, /* R227 - misc overrides */
+ 0x0000, /* R228 - Supply overrides/status 1 */
+ 0x0000, /* R229 - Supply overrides/status 2 */
+ 0xE000, /* R230 - GPIO Pin Status */
+ 0x0000, /* R231 - comparotor overrides */
+ 0x0000, /* R232 */
+ 0x0000, /* R233 - State Machine status */
+ 0x1200, /* R234 - FLL Test 1 */
+ 0x0000, /* R235 */
+ 0x8000, /* R236 */
+ 0x0000, /* R237 */
+ 0x0000, /* R238 */
+ 0x0000, /* R239 */
+ 0x0003, /* R240 */
+ 0x0000, /* R241 */
+ 0x0000, /* R242 */
+ 0x0004, /* R243 */
+ 0x0300, /* R244 */
+ 0x0000, /* R245 */
+ 0x0200, /* R246 */
+ 0x0000, /* R247 */
+ 0x1000, /* R248 - DCDC1 Test Controls */
+ 0x1000, /* R249 */
+ 0x1000, /* R250 - DCDC3 Test Controls */
+ 0x1000, /* R251 - DCDC4 Test Controls */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_1
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8351_mode1_defaults[] = {
+ 0x6143, /* R0 - Reset/ID */
+ 0x0000, /* R1 - ID */
+ 0x0001, /* R2 - Revision */
+ 0x1C02, /* R3 - System Control 1 */
+ 0x0204, /* R4 - System Control 2 */
+ 0x0000, /* R5 - System Hibernate */
+ 0x8A00, /* R6 - Interface Control */
+ 0x0000, /* R7 */
+ 0x8000, /* R8 - Power mgmt (1) */
+ 0x0000, /* R9 - Power mgmt (2) */
+ 0x0000, /* R10 - Power mgmt (3) */
+ 0x2000, /* R11 - Power mgmt (4) */
+ 0x0E00, /* R12 - Power mgmt (5) */
+ 0x0000, /* R13 - Power mgmt (6) */
+ 0x0000, /* R14 - Power mgmt (7) */
+ 0x0000, /* R15 */
+ 0x0000, /* R16 - RTC Seconds/Minutes */
+ 0x0100, /* R17 - RTC Hours/Day */
+ 0x0101, /* R18 - RTC Date/Month */
+ 0x1400, /* R19 - RTC Year */
+ 0x0000, /* R20 - Alarm Seconds/Minutes */
+ 0x0000, /* R21 - Alarm Hours/Day */
+ 0x0000, /* R22 - Alarm Date/Month */
+ 0x0320, /* R23 - RTC Time Control */
+ 0x0000, /* R24 - System Interrupts */
+ 0x0000, /* R25 - Interrupt Status 1 */
+ 0x0000, /* R26 - Interrupt Status 2 */
+ 0x0000, /* R27 */
+ 0x0000, /* R28 - Under Voltage Interrupt status */
+ 0x0000, /* R29 - Over Current Interrupt status */
+ 0x0000, /* R30 - GPIO Interrupt Status */
+ 0x0000, /* R31 - Comparator Interrupt Status */
+ 0x3FFF, /* R32 - System Interrupts Mask */
+ 0x0000, /* R33 - Interrupt Status 1 Mask */
+ 0x0000, /* R34 - Interrupt Status 2 Mask */
+ 0x0000, /* R35 */
+ 0x0000, /* R36 - Under Voltage Interrupt status Mask */
+ 0x0000, /* R37 - Over Current Interrupt status Mask */
+ 0x0000, /* R38 - GPIO Interrupt Status Mask */
+ 0x0000, /* R39 - Comparator Interrupt Status Mask */
+ 0x0040, /* R40 - Clock Control 1 */
+ 0x0000, /* R41 - Clock Control 2 */
+ 0x3A00, /* R42 - FLL Control 1 */
+ 0x7086, /* R43 - FLL Control 2 */
+ 0xC226, /* R44 - FLL Control 3 */
+ 0x0000, /* R45 - FLL Control 4 */
+ 0x0000, /* R46 */
+ 0x0000, /* R47 */
+ 0x0000, /* R48 - DAC Control */
+ 0x0000, /* R49 */
+ 0x00C0, /* R50 - DAC Digital Volume L */
+ 0x00C0, /* R51 - DAC Digital Volume R */
+ 0x0000, /* R52 */
+ 0x0040, /* R53 - DAC LR Rate */
+ 0x0000, /* R54 - DAC Clock Control */
+ 0x0000, /* R55 */
+ 0x0000, /* R56 */
+ 0x0000, /* R57 */
+ 0x4000, /* R58 - DAC Mute */
+ 0x0000, /* R59 - DAC Mute Volume */
+ 0x0000, /* R60 - DAC Side */
+ 0x0000, /* R61 */
+ 0x0000, /* R62 */
+ 0x0000, /* R63 */
+ 0x8000, /* R64 - ADC Control */
+ 0x0000, /* R65 */
+ 0x00C0, /* R66 - ADC Digital Volume L */
+ 0x00C0, /* R67 - ADC Digital Volume R */
+ 0x0000, /* R68 - ADC Divider */
+ 0x0000, /* R69 */
+ 0x0040, /* R70 - ADC LR Rate */
+ 0x0000, /* R71 */
+ 0x0303, /* R72 - Input Control */
+ 0x0000, /* R73 - IN3 Input Control */
+ 0x0000, /* R74 - Mic Bias Control */
+ 0x0000, /* R75 */
+ 0x0000, /* R76 - Output Control */
+ 0x0000, /* R77 - Jack Detect */
+ 0x0000, /* R78 - Anti Pop Control */
+ 0x0000, /* R79 */
+ 0x0040, /* R80 - Left Input Volume */
+ 0x0040, /* R81 - Right Input Volume */
+ 0x0000, /* R82 */
+ 0x0000, /* R83 */
+ 0x0000, /* R84 */
+ 0x0000, /* R85 */
+ 0x0000, /* R86 */
+ 0x0000, /* R87 */
+ 0x0800, /* R88 - Left Mixer Control */
+ 0x1000, /* R89 - Right Mixer Control */
+ 0x0000, /* R90 */
+ 0x0000, /* R91 */
+ 0x0000, /* R92 - OUT3 Mixer Control */
+ 0x0000, /* R93 - OUT4 Mixer Control */
+ 0x0000, /* R94 */
+ 0x0000, /* R95 */
+ 0x0000, /* R96 - Output Left Mixer Volume */
+ 0x0000, /* R97 - Output Right Mixer Volume */
+ 0x0000, /* R98 - Input Mixer Volume L */
+ 0x0000, /* R99 - Input Mixer Volume R */
+ 0x0000, /* R100 - Input Mixer Volume */
+ 0x0000, /* R101 */
+ 0x0000, /* R102 */
+ 0x0000, /* R103 */
+ 0x00E4, /* R104 - OUT1L Volume */
+ 0x00E4, /* R105 - OUT1R Volume */
+ 0x00E4, /* R106 - OUT2L Volume */
+ 0x02E4, /* R107 - OUT2R Volume */
+ 0x0000, /* R108 */
+ 0x0000, /* R109 */
+ 0x0000, /* R110 */
+ 0x0000, /* R111 - BEEP Volume */
+ 0x0A00, /* R112 - AI Formating */
+ 0x0000, /* R113 - ADC DAC COMP */
+ 0x0020, /* R114 - AI ADC Control */
+ 0x0020, /* R115 - AI DAC Control */
+ 0x0000, /* R116 */
+ 0x0000, /* R117 */
+ 0x0000, /* R118 */
+ 0x0000, /* R119 */
+ 0x0000, /* R120 */
+ 0x0000, /* R121 */
+ 0x0000, /* R122 */
+ 0x0000, /* R123 */
+ 0x0000, /* R124 */
+ 0x0000, /* R125 */
+ 0x0000, /* R126 */
+ 0x0000, /* R127 */
+ 0x1FFF, /* R128 - GPIO Debounce */
+ 0x0000, /* R129 - GPIO Pin pull up Control */
+ 0x0000, /* R130 - GPIO Pull down Control */
+ 0x0000, /* R131 - GPIO Interrupt Mode */
+ 0x0000, /* R132 */
+ 0x0000, /* R133 - GPIO Control */
+ 0x0CFB, /* R134 - GPIO Configuration (i/o) */
+ 0x0C1F, /* R135 - GPIO Pin Polarity / Type */
+ 0x0000, /* R136 */
+ 0x0000, /* R137 */
+ 0x0000, /* R138 */
+ 0x0000, /* R139 */
+ 0x0300, /* R140 - GPIO Function Select 1 */
+ 0x1110, /* R141 - GPIO Function Select 2 */
+ 0x0013, /* R142 - GPIO Function Select 3 */
+ 0x0003, /* R143 - GPIO Function Select 4 */
+ 0x0000, /* R144 - Digitiser Control (1) */
+ 0x0002, /* R145 - Digitiser Control (2) */
+ 0x0000, /* R146 */
+ 0x0000, /* R147 */
+ 0x0000, /* R148 */
+ 0x0000, /* R149 */
+ 0x0000, /* R150 */
+ 0x0000, /* R151 */
+ 0x7000, /* R152 - AUX1 Readback */
+ 0x7000, /* R153 - AUX2 Readback */
+ 0x7000, /* R154 - AUX3 Readback */
+ 0x7000, /* R155 - AUX4 Readback */
+ 0x0000, /* R156 - USB Voltage Readback */
+ 0x0000, /* R157 - LINE Voltage Readback */
+ 0x0000, /* R158 - BATT Voltage Readback */
+ 0x0000, /* R159 - Chip Temp Readback */
+ 0x0000, /* R160 */
+ 0x0000, /* R161 */
+ 0x0000, /* R162 */
+ 0x0000, /* R163 - Generic Comparator Control */
+ 0x0000, /* R164 - Generic comparator 1 */
+ 0x0000, /* R165 - Generic comparator 2 */
+ 0x0000, /* R166 - Generic comparator 3 */
+ 0x0000, /* R167 - Generic comparator 4 */
+ 0xA00F, /* R168 - Battery Charger Control 1 */
+ 0x0B06, /* R169 - Battery Charger Control 2 */
+ 0x0000, /* R170 - Battery Charger Control 3 */
+ 0x0000, /* R171 */
+ 0x0000, /* R172 - Current Sink Driver A */
+ 0x0000, /* R173 - CSA Flash control */
+ 0x0000, /* R174 */
+ 0x0000, /* R175 */
+ 0x0000, /* R176 - DCDC/LDO requested */
+ 0x032D, /* R177 - DCDC Active options */
+ 0x0000, /* R178 - DCDC Sleep options */
+ 0x0025, /* R179 - Power-check comparator */
+ 0x000E, /* R180 - DCDC1 Control */
+ 0x0C00, /* R181 - DCDC1 Timeouts */
+ 0x1006, /* R182 - DCDC1 Low Power */
+ 0x0018, /* R183 - DCDC2 Control */
+ 0x0000, /* R184 - DCDC2 Timeouts */
+ 0x0000, /* R185 */
+ 0x0026, /* R186 - DCDC3 Control */
+ 0x0400, /* R187 - DCDC3 Timeouts */
+ 0x0006, /* R188 - DCDC3 Low Power */
+ 0x0062, /* R189 - DCDC4 Control */
+ 0x0800, /* R190 - DCDC4 Timeouts */
+ 0x0006, /* R191 - DCDC4 Low Power */
+ 0x0008, /* R192 */
+ 0x0000, /* R193 */
+ 0x0000, /* R194 */
+ 0x000A, /* R195 */
+ 0x1000, /* R196 */
+ 0x0006, /* R197 */
+ 0x0000, /* R198 */
+ 0x0003, /* R199 - Limit Switch Control */
+ 0x0006, /* R200 - LDO1 Control */
+ 0x0000, /* R201 - LDO1 Timeouts */
+ 0x001C, /* R202 - LDO1 Low Power */
+ 0x0010, /* R203 - LDO2 Control */
+ 0x0C00, /* R204 - LDO2 Timeouts */
+ 0x001C, /* R205 - LDO2 Low Power */
+ 0x001F, /* R206 - LDO3 Control */
+ 0x0800, /* R207 - LDO3 Timeouts */
+ 0x001C, /* R208 - LDO3 Low Power */
+ 0x000A, /* R209 - LDO4 Control */
+ 0x0800, /* R210 - LDO4 Timeouts */
+ 0x001C, /* R211 - LDO4 Low Power */
+ 0x0000, /* R212 */
+ 0x0000, /* R213 */
+ 0x0000, /* R214 */
+ 0x0000, /* R215 - VCC_FAULT Masks */
+ 0x001F, /* R216 - Main Bandgap Control */
+ 0x0000, /* R217 - OSC Control */
+ 0x9000, /* R218 - RTC Tick Control */
+ 0x0000, /* R219 - Security1 */
+ 0x4000, /* R220 */
+ 0x0000, /* R221 */
+ 0x0000, /* R222 */
+ 0x0000, /* R223 */
+ 0x0000, /* R224 - Signal overrides */
+ 0x0000, /* R225 - DCDC/LDO status */
+ 0x0000, /* R226 - Charger Overides/status */
+ 0x0000, /* R227 - misc overrides */
+ 0x0000, /* R228 - Supply overrides/status 1 */
+ 0x0000, /* R229 - Supply overrides/status 2 */
+ 0xE000, /* R230 - GPIO Pin Status */
+ 0x0000, /* R231 - comparotor overrides */
+ 0x0000, /* R232 */
+ 0x0000, /* R233 - State Machine status */
+ 0x1200, /* R234 - FLL Test 1 */
+ 0x0000, /* R235 */
+ 0x8000, /* R236 */
+ 0x0000, /* R237 */
+ 0x0000, /* R238 */
+ 0x0000, /* R239 */
+ 0x0003, /* R240 */
+ 0x0000, /* R241 */
+ 0x0000, /* R242 */
+ 0x0004, /* R243 */
+ 0x0300, /* R244 */
+ 0x0000, /* R245 */
+ 0x0200, /* R246 */
+ 0x1000, /* R247 */
+ 0x1000, /* R248 - DCDC1 Test Controls */
+ 0x1000, /* R249 */
+ 0x1000, /* R250 - DCDC3 Test Controls */
+ 0x1000, /* R251 - DCDC4 Test Controls */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_2
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8351_mode2_defaults[] = {
+ 0x6143, /* R0 - Reset/ID */
+ 0x0000, /* R1 - ID */
+ 0x0001, /* R2 - Revision */
+ 0x1C02, /* R3 - System Control 1 */
+ 0x0214, /* R4 - System Control 2 */
+ 0x0000, /* R5 - System Hibernate */
+ 0x8A00, /* R6 - Interface Control */
+ 0x0000, /* R7 */
+ 0x8000, /* R8 - Power mgmt (1) */
+ 0x0000, /* R9 - Power mgmt (2) */
+ 0x0000, /* R10 - Power mgmt (3) */
+ 0x2000, /* R11 - Power mgmt (4) */
+ 0x0E00, /* R12 - Power mgmt (5) */
+ 0x0000, /* R13 - Power mgmt (6) */
+ 0x0000, /* R14 - Power mgmt (7) */
+ 0x0000, /* R15 */
+ 0x0000, /* R16 - RTC Seconds/Minutes */
+ 0x0100, /* R17 - RTC Hours/Day */
+ 0x0101, /* R18 - RTC Date/Month */
+ 0x1400, /* R19 - RTC Year */
+ 0x0000, /* R20 - Alarm Seconds/Minutes */
+ 0x0000, /* R21 - Alarm Hours/Day */
+ 0x0000, /* R22 - Alarm Date/Month */
+ 0x0320, /* R23 - RTC Time Control */
+ 0x0000, /* R24 - System Interrupts */
+ 0x0000, /* R25 - Interrupt Status 1 */
+ 0x0000, /* R26 - Interrupt Status 2 */
+ 0x0000, /* R27 */
+ 0x0000, /* R28 - Under Voltage Interrupt status */
+ 0x0000, /* R29 - Over Current Interrupt status */
+ 0x0000, /* R30 - GPIO Interrupt Status */
+ 0x0000, /* R31 - Comparator Interrupt Status */
+ 0x3FFF, /* R32 - System Interrupts Mask */
+ 0x0000, /* R33 - Interrupt Status 1 Mask */
+ 0x0000, /* R34 - Interrupt Status 2 Mask */
+ 0x0000, /* R35 */
+ 0x0000, /* R36 - Under Voltage Interrupt status Mask */
+ 0x0000, /* R37 - Over Current Interrupt status Mask */
+ 0x0000, /* R38 - GPIO Interrupt Status Mask */
+ 0x0000, /* R39 - Comparator Interrupt Status Mask */
+ 0x0040, /* R40 - Clock Control 1 */
+ 0x0000, /* R41 - Clock Control 2 */
+ 0x3A00, /* R42 - FLL Control 1 */
+ 0x7086, /* R43 - FLL Control 2 */
+ 0xC226, /* R44 - FLL Control 3 */
+ 0x0000, /* R45 - FLL Control 4 */
+ 0x0000, /* R46 */
+ 0x0000, /* R47 */
+ 0x0000, /* R48 - DAC Control */
+ 0x0000, /* R49 */
+ 0x00C0, /* R50 - DAC Digital Volume L */
+ 0x00C0, /* R51 - DAC Digital Volume R */
+ 0x0000, /* R52 */
+ 0x0040, /* R53 - DAC LR Rate */
+ 0x0000, /* R54 - DAC Clock Control */
+ 0x0000, /* R55 */
+ 0x0000, /* R56 */
+ 0x0000, /* R57 */
+ 0x4000, /* R58 - DAC Mute */
+ 0x0000, /* R59 - DAC Mute Volume */
+ 0x0000, /* R60 - DAC Side */
+ 0x0000, /* R61 */
+ 0x0000, /* R62 */
+ 0x0000, /* R63 */
+ 0x8000, /* R64 - ADC Control */
+ 0x0000, /* R65 */
+ 0x00C0, /* R66 - ADC Digital Volume L */
+ 0x00C0, /* R67 - ADC Digital Volume R */
+ 0x0000, /* R68 - ADC Divider */
+ 0x0000, /* R69 */
+ 0x0040, /* R70 - ADC LR Rate */
+ 0x0000, /* R71 */
+ 0x0303, /* R72 - Input Control */
+ 0x0000, /* R73 - IN3 Input Control */
+ 0x0000, /* R74 - Mic Bias Control */
+ 0x0000, /* R75 */
+ 0x0000, /* R76 - Output Control */
+ 0x0000, /* R77 - Jack Detect */
+ 0x0000, /* R78 - Anti Pop Control */
+ 0x0000, /* R79 */
+ 0x0040, /* R80 - Left Input Volume */
+ 0x0040, /* R81 - Right Input Volume */
+ 0x0000, /* R82 */
+ 0x0000, /* R83 */
+ 0x0000, /* R84 */
+ 0x0000, /* R85 */
+ 0x0000, /* R86 */
+ 0x0000, /* R87 */
+ 0x0800, /* R88 - Left Mixer Control */
+ 0x1000, /* R89 - Right Mixer Control */
+ 0x0000, /* R90 */
+ 0x0000, /* R91 */
+ 0x0000, /* R92 - OUT3 Mixer Control */
+ 0x0000, /* R93 - OUT4 Mixer Control */
+ 0x0000, /* R94 */
+ 0x0000, /* R95 */
+ 0x0000, /* R96 - Output Left Mixer Volume */
+ 0x0000, /* R97 - Output Right Mixer Volume */
+ 0x0000, /* R98 - Input Mixer Volume L */
+ 0x0000, /* R99 - Input Mixer Volume R */
+ 0x0000, /* R100 - Input Mixer Volume */
+ 0x0000, /* R101 */
+ 0x0000, /* R102 */
+ 0x0000, /* R103 */
+ 0x00E4, /* R104 - OUT1L Volume */
+ 0x00E4, /* R105 - OUT1R Volume */
+ 0x00E4, /* R106 - OUT2L Volume */
+ 0x02E4, /* R107 - OUT2R Volume */
+ 0x0000, /* R108 */
+ 0x0000, /* R109 */
+ 0x0000, /* R110 */
+ 0x0000, /* R111 - BEEP Volume */
+ 0x0A00, /* R112 - AI Formating */
+ 0x0000, /* R113 - ADC DAC COMP */
+ 0x0020, /* R114 - AI ADC Control */
+ 0x0020, /* R115 - AI DAC Control */
+ 0x0000, /* R116 */
+ 0x0000, /* R117 */
+ 0x0000, /* R118 */
+ 0x0000, /* R119 */
+ 0x0000, /* R120 */
+ 0x0000, /* R121 */
+ 0x0000, /* R122 */
+ 0x0000, /* R123 */
+ 0x0000, /* R124 */
+ 0x0000, /* R125 */
+ 0x0000, /* R126 */
+ 0x0000, /* R127 */
+ 0x1FFF, /* R128 - GPIO Debounce */
+ 0x0000, /* R129 - GPIO Pin pull up Control */
+ 0x0110, /* R130 - GPIO Pull down Control */
+ 0x0000, /* R131 - GPIO Interrupt Mode */
+ 0x0000, /* R132 */
+ 0x0000, /* R133 - GPIO Control */
+ 0x09FA, /* R134 - GPIO Configuration (i/o) */
+ 0x0DF6, /* R135 - GPIO Pin Polarity / Type */
+ 0x0000, /* R136 */
+ 0x0000, /* R137 */
+ 0x0000, /* R138 */
+ 0x0000, /* R139 */
+ 0x1310, /* R140 - GPIO Function Select 1 */
+ 0x0003, /* R141 - GPIO Function Select 2 */
+ 0x2000, /* R142 - GPIO Function Select 3 */
+ 0x0000, /* R143 - GPIO Function Select 4 */
+ 0x0000, /* R144 - Digitiser Control (1) */
+ 0x0002, /* R145 - Digitiser Control (2) */
+ 0x0000, /* R146 */
+ 0x0000, /* R147 */
+ 0x0000, /* R148 */
+ 0x0000, /* R149 */
+ 0x0000, /* R150 */
+ 0x0000, /* R151 */
+ 0x7000, /* R152 - AUX1 Readback */
+ 0x7000, /* R153 - AUX2 Readback */
+ 0x7000, /* R154 - AUX3 Readback */
+ 0x7000, /* R155 - AUX4 Readback */
+ 0x0000, /* R156 - USB Voltage Readback */
+ 0x0000, /* R157 - LINE Voltage Readback */
+ 0x0000, /* R158 - BATT Voltage Readback */
+ 0x0000, /* R159 - Chip Temp Readback */
+ 0x0000, /* R160 */
+ 0x0000, /* R161 */
+ 0x0000, /* R162 */
+ 0x0000, /* R163 - Generic Comparator Control */
+ 0x0000, /* R164 - Generic comparator 1 */
+ 0x0000, /* R165 - Generic comparator 2 */
+ 0x0000, /* R166 - Generic comparator 3 */
+ 0x0000, /* R167 - Generic comparator 4 */
+ 0xA00F, /* R168 - Battery Charger Control 1 */
+ 0x0B06, /* R169 - Battery Charger Control 2 */
+ 0x0000, /* R170 - Battery Charger Control 3 */
+ 0x0000, /* R171 */
+ 0x0000, /* R172 - Current Sink Driver A */
+ 0x0000, /* R173 - CSA Flash control */
+ 0x0000, /* R174 */
+ 0x0000, /* R175 */
+ 0x0000, /* R176 - DCDC/LDO requested */
+ 0x032D, /* R177 - DCDC Active options */
+ 0x0000, /* R178 - DCDC Sleep options */
+ 0x0025, /* R179 - Power-check comparator */
+ 0x001A, /* R180 - DCDC1 Control */
+ 0x0800, /* R181 - DCDC1 Timeouts */
+ 0x1006, /* R182 - DCDC1 Low Power */
+ 0x0018, /* R183 - DCDC2 Control */
+ 0x0000, /* R184 - DCDC2 Timeouts */
+ 0x0000, /* R185 */
+ 0x0056, /* R186 - DCDC3 Control */
+ 0x0400, /* R187 - DCDC3 Timeouts */
+ 0x0006, /* R188 - DCDC3 Low Power */
+ 0x0026, /* R189 - DCDC4 Control */
+ 0x0C00, /* R190 - DCDC4 Timeouts */
+ 0x0006, /* R191 - DCDC4 Low Power */
+ 0x0008, /* R192 */
+ 0x0000, /* R193 */
+ 0x0000, /* R194 */
+ 0x0026, /* R195 */
+ 0x0C00, /* R196 */
+ 0x0006, /* R197 */
+ 0x0000, /* R198 */
+ 0x0003, /* R199 - Limit Switch Control */
+ 0x001C, /* R200 - LDO1 Control */
+ 0x0400, /* R201 - LDO1 Timeouts */
+ 0x001C, /* R202 - LDO1 Low Power */
+ 0x0010, /* R203 - LDO2 Control */
+ 0x0C00, /* R204 - LDO2 Timeouts */
+ 0x001C, /* R205 - LDO2 Low Power */
+ 0x0015, /* R206 - LDO3 Control */
+ 0x0000, /* R207 - LDO3 Timeouts */
+ 0x001C, /* R208 - LDO3 Low Power */
+ 0x001A, /* R209 - LDO4 Control */
+ 0x0000, /* R210 - LDO4 Timeouts */
+ 0x001C, /* R211 - LDO4 Low Power */
+ 0x0000, /* R212 */
+ 0x0000, /* R213 */
+ 0x0000, /* R214 */
+ 0x0000, /* R215 - VCC_FAULT Masks */
+ 0x001F, /* R216 - Main Bandgap Control */
+ 0x0000, /* R217 - OSC Control */
+ 0x9000, /* R218 - RTC Tick Control */
+ 0x0000, /* R219 - Security1 */
+ 0x4000, /* R220 */
+ 0x0000, /* R221 */
+ 0x0000, /* R222 */
+ 0x0000, /* R223 */
+ 0x0000, /* R224 - Signal overrides */
+ 0x0000, /* R225 - DCDC/LDO status */
+ 0x0000, /* R226 - Charger Overides/status */
+ 0x0000, /* R227 - misc overrides */
+ 0x0000, /* R228 - Supply overrides/status 1 */
+ 0x0000, /* R229 - Supply overrides/status 2 */
+ 0xE000, /* R230 - GPIO Pin Status */
+ 0x0000, /* R231 - comparotor overrides */
+ 0x0000, /* R232 */
+ 0x0000, /* R233 - State Machine status */
+ 0x1200, /* R234 - FLL Test 1 */
+ 0x0000, /* R235 */
+ 0x8000, /* R236 */
+ 0x0000, /* R237 */
+ 0x0000, /* R238 */
+ 0x0000, /* R239 */
+ 0x0003, /* R240 */
+ 0x0000, /* R241 */
+ 0x0000, /* R242 */
+ 0x0004, /* R243 */
+ 0x0300, /* R244 */
+ 0x0000, /* R245 */
+ 0x0200, /* R246 */
+ 0x0000, /* R247 */
+ 0x1000, /* R248 - DCDC1 Test Controls */
+ 0x1000, /* R249 */
+ 0x1000, /* R250 - DCDC3 Test Controls */
+ 0x1000, /* R251 - DCDC4 Test Controls */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_3
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8351_mode3_defaults[] = {
+ 0x6143, /* R0 - Reset/ID */
+ 0x0000, /* R1 - ID */
+ 0x0001, /* R2 - Revision */
+ 0x1C02, /* R3 - System Control 1 */
+ 0x0204, /* R4 - System Control 2 */
+ 0x0000, /* R5 - System Hibernate */
+ 0x8A00, /* R6 - Interface Control */
+ 0x0000, /* R7 */
+ 0x8000, /* R8 - Power mgmt (1) */
+ 0x0000, /* R9 - Power mgmt (2) */
+ 0x0000, /* R10 - Power mgmt (3) */
+ 0x2000, /* R11 - Power mgmt (4) */
+ 0x0E00, /* R12 - Power mgmt (5) */
+ 0x0000, /* R13 - Power mgmt (6) */
+ 0x0000, /* R14 - Power mgmt (7) */
+ 0x0000, /* R15 */
+ 0x0000, /* R16 - RTC Seconds/Minutes */
+ 0x0100, /* R17 - RTC Hours/Day */
+ 0x0101, /* R18 - RTC Date/Month */
+ 0x1400, /* R19 - RTC Year */
+ 0x0000, /* R20 - Alarm Seconds/Minutes */
+ 0x0000, /* R21 - Alarm Hours/Day */
+ 0x0000, /* R22 - Alarm Date/Month */
+ 0x0320, /* R23 - RTC Time Control */
+ 0x0000, /* R24 - System Interrupts */
+ 0x0000, /* R25 - Interrupt Status 1 */
+ 0x0000, /* R26 - Interrupt Status 2 */
+ 0x0000, /* R27 */
+ 0x0000, /* R28 - Under Voltage Interrupt status */
+ 0x0000, /* R29 - Over Current Interrupt status */
+ 0x0000, /* R30 - GPIO Interrupt Status */
+ 0x0000, /* R31 - Comparator Interrupt Status */
+ 0x3FFF, /* R32 - System Interrupts Mask */
+ 0x0000, /* R33 - Interrupt Status 1 Mask */
+ 0x0000, /* R34 - Interrupt Status 2 Mask */
+ 0x0000, /* R35 */
+ 0x0000, /* R36 - Under Voltage Interrupt status Mask */
+ 0x0000, /* R37 - Over Current Interrupt status Mask */
+ 0x0000, /* R38 - GPIO Interrupt Status Mask */
+ 0x0000, /* R39 - Comparator Interrupt Status Mask */
+ 0x0040, /* R40 - Clock Control 1 */
+ 0x0000, /* R41 - Clock Control 2 */
+ 0x3A00, /* R42 - FLL Control 1 */
+ 0x7086, /* R43 - FLL Control 2 */
+ 0xC226, /* R44 - FLL Control 3 */
+ 0x0000, /* R45 - FLL Control 4 */
+ 0x0000, /* R46 */
+ 0x0000, /* R47 */
+ 0x0000, /* R48 - DAC Control */
+ 0x0000, /* R49 */
+ 0x00C0, /* R50 - DAC Digital Volume L */
+ 0x00C0, /* R51 - DAC Digital Volume R */
+ 0x0000, /* R52 */
+ 0x0040, /* R53 - DAC LR Rate */
+ 0x0000, /* R54 - DAC Clock Control */
+ 0x0000, /* R55 */
+ 0x0000, /* R56 */
+ 0x0000, /* R57 */
+ 0x4000, /* R58 - DAC Mute */
+ 0x0000, /* R59 - DAC Mute Volume */
+ 0x0000, /* R60 - DAC Side */
+ 0x0000, /* R61 */
+ 0x0000, /* R62 */
+ 0x0000, /* R63 */
+ 0x8000, /* R64 - ADC Control */
+ 0x0000, /* R65 */
+ 0x00C0, /* R66 - ADC Digital Volume L */
+ 0x00C0, /* R67 - ADC Digital Volume R */
+ 0x0000, /* R68 - ADC Divider */
+ 0x0000, /* R69 */
+ 0x0040, /* R70 - ADC LR Rate */
+ 0x0000, /* R71 */
+ 0x0303, /* R72 - Input Control */
+ 0x0000, /* R73 - IN3 Input Control */
+ 0x0000, /* R74 - Mic Bias Control */
+ 0x0000, /* R75 */
+ 0x0000, /* R76 - Output Control */
+ 0x0000, /* R77 - Jack Detect */
+ 0x0000, /* R78 - Anti Pop Control */
+ 0x0000, /* R79 */
+ 0x0040, /* R80 - Left Input Volume */
+ 0x0040, /* R81 - Right Input Volume */
+ 0x0000, /* R82 */
+ 0x0000, /* R83 */
+ 0x0000, /* R84 */
+ 0x0000, /* R85 */
+ 0x0000, /* R86 */
+ 0x0000, /* R87 */
+ 0x0800, /* R88 - Left Mixer Control */
+ 0x1000, /* R89 - Right Mixer Control */
+ 0x0000, /* R90 */
+ 0x0000, /* R91 */
+ 0x0000, /* R92 - OUT3 Mixer Control */
+ 0x0000, /* R93 - OUT4 Mixer Control */
+ 0x0000, /* R94 */
+ 0x0000, /* R95 */
+ 0x0000, /* R96 - Output Left Mixer Volume */
+ 0x0000, /* R97 - Output Right Mixer Volume */
+ 0x0000, /* R98 - Input Mixer Volume L */
+ 0x0000, /* R99 - Input Mixer Volume R */
+ 0x0000, /* R100 - Input Mixer Volume */
+ 0x0000, /* R101 */
+ 0x0000, /* R102 */
+ 0x0000, /* R103 */
+ 0x00E4, /* R104 - OUT1L Volume */
+ 0x00E4, /* R105 - OUT1R Volume */
+ 0x00E4, /* R106 - OUT2L Volume */
+ 0x02E4, /* R107 - OUT2R Volume */
+ 0x0000, /* R108 */
+ 0x0000, /* R109 */
+ 0x0000, /* R110 */
+ 0x0000, /* R111 - BEEP Volume */
+ 0x0A00, /* R112 - AI Formating */
+ 0x0000, /* R113 - ADC DAC COMP */
+ 0x0020, /* R114 - AI ADC Control */
+ 0x0020, /* R115 - AI DAC Control */
+ 0x0000, /* R116 */
+ 0x0000, /* R117 */
+ 0x0000, /* R118 */
+ 0x0000, /* R119 */
+ 0x0000, /* R120 */
+ 0x0000, /* R121 */
+ 0x0000, /* R122 */
+ 0x0000, /* R123 */
+ 0x0000, /* R124 */
+ 0x0000, /* R125 */
+ 0x0000, /* R126 */
+ 0x0000, /* R127 */
+ 0x1FFF, /* R128 - GPIO Debounce */
+ 0x0010, /* R129 - GPIO Pin pull up Control */
+ 0x0000, /* R130 - GPIO Pull down Control */
+ 0x0000, /* R131 - GPIO Interrupt Mode */
+ 0x0000, /* R132 */
+ 0x0000, /* R133 - GPIO Control */
+ 0x0BFB, /* R134 - GPIO Configuration (i/o) */
+ 0x0FFD, /* R135 - GPIO Pin Polarity / Type */
+ 0x0000, /* R136 */
+ 0x0000, /* R137 */
+ 0x0000, /* R138 */
+ 0x0000, /* R139 */
+ 0x0310, /* R140 - GPIO Function Select 1 */
+ 0x0001, /* R141 - GPIO Function Select 2 */
+ 0x2300, /* R142 - GPIO Function Select 3 */
+ 0x0003, /* R143 - GPIO Function Select 4 */
+ 0x0000, /* R144 - Digitiser Control (1) */
+ 0x0002, /* R145 - Digitiser Control (2) */
+ 0x0000, /* R146 */
+ 0x0000, /* R147 */
+ 0x0000, /* R148 */
+ 0x0000, /* R149 */
+ 0x0000, /* R150 */
+ 0x0000, /* R151 */
+ 0x7000, /* R152 - AUX1 Readback */
+ 0x7000, /* R153 - AUX2 Readback */
+ 0x7000, /* R154 - AUX3 Readback */
+ 0x7000, /* R155 - AUX4 Readback */
+ 0x0000, /* R156 - USB Voltage Readback */
+ 0x0000, /* R157 - LINE Voltage Readback */
+ 0x0000, /* R158 - BATT Voltage Readback */
+ 0x0000, /* R159 - Chip Temp Readback */
+ 0x0000, /* R160 */
+ 0x0000, /* R161 */
+ 0x0000, /* R162 */
+ 0x0000, /* R163 - Generic Comparator Control */
+ 0x0000, /* R164 - Generic comparator 1 */
+ 0x0000, /* R165 - Generic comparator 2 */
+ 0x0000, /* R166 - Generic comparator 3 */
+ 0x0000, /* R167 - Generic comparator 4 */
+ 0xA00F, /* R168 - Battery Charger Control 1 */
+ 0x0B06, /* R169 - Battery Charger Control 2 */
+ 0x0000, /* R170 - Battery Charger Control 3 */
+ 0x0000, /* R171 */
+ 0x0000, /* R172 - Current Sink Driver A */
+ 0x0000, /* R173 - CSA Flash control */
+ 0x0000, /* R174 */
+ 0x0000, /* R175 */
+ 0x0000, /* R176 - DCDC/LDO requested */
+ 0x032D, /* R177 - DCDC Active options */
+ 0x0000, /* R178 - DCDC Sleep options */
+ 0x0025, /* R179 - Power-check comparator */
+ 0x000E, /* R180 - DCDC1 Control */
+ 0x0400, /* R181 - DCDC1 Timeouts */
+ 0x1006, /* R182 - DCDC1 Low Power */
+ 0x0018, /* R183 - DCDC2 Control */
+ 0x0000, /* R184 - DCDC2 Timeouts */
+ 0x0000, /* R185 */
+ 0x0026, /* R186 - DCDC3 Control */
+ 0x0800, /* R187 - DCDC3 Timeouts */
+ 0x0006, /* R188 - DCDC3 Low Power */
+ 0x0062, /* R189 - DCDC4 Control */
+ 0x1400, /* R190 - DCDC4 Timeouts */
+ 0x0006, /* R191 - DCDC4 Low Power */
+ 0x0008, /* R192 */
+ 0x0000, /* R193 */
+ 0x0000, /* R194 */
+ 0x0026, /* R195 */
+ 0x0400, /* R196 */
+ 0x0006, /* R197 */
+ 0x0000, /* R198 */
+ 0x0003, /* R199 - Limit Switch Control */
+ 0x0006, /* R200 - LDO1 Control */
+ 0x0C00, /* R201 - LDO1 Timeouts */
+ 0x001C, /* R202 - LDO1 Low Power */
+ 0x0016, /* R203 - LDO2 Control */
+ 0x0000, /* R204 - LDO2 Timeouts */
+ 0x001C, /* R205 - LDO2 Low Power */
+ 0x0019, /* R206 - LDO3 Control */
+ 0x0000, /* R207 - LDO3 Timeouts */
+ 0x001C, /* R208 - LDO3 Low Power */
+ 0x001A, /* R209 - LDO4 Control */
+ 0x1000, /* R210 - LDO4 Timeouts */
+ 0x001C, /* R211 - LDO4 Low Power */
+ 0x0000, /* R212 */
+ 0x0000, /* R213 */
+ 0x0000, /* R214 */
+ 0x0000, /* R215 - VCC_FAULT Masks */
+ 0x001F, /* R216 - Main Bandgap Control */
+ 0x0000, /* R217 - OSC Control */
+ 0x9000, /* R218 - RTC Tick Control */
+ 0x0000, /* R219 - Security1 */
+ 0x4000, /* R220 */
+ 0x0000, /* R221 */
+ 0x0000, /* R222 */
+ 0x0000, /* R223 */
+ 0x0000, /* R224 - Signal overrides */
+ 0x0000, /* R225 - DCDC/LDO status */
+ 0x0000, /* R226 - Charger Overides/status */
+ 0x0000, /* R227 - misc overrides */
+ 0x0000, /* R228 - Supply overrides/status 1 */
+ 0x0000, /* R229 - Supply overrides/status 2 */
+ 0xE000, /* R230 - GPIO Pin Status */
+ 0x0000, /* R231 - comparotor overrides */
+ 0x0000, /* R232 */
+ 0x0000, /* R233 - State Machine status */
+ 0x1200, /* R234 - FLL Test 1 */
+ 0x0000, /* R235 */
+ 0x8000, /* R236 */
+ 0x0000, /* R237 */
+ 0x0000, /* R238 */
+ 0x0000, /* R239 */
+ 0x0003, /* R240 */
+ 0x0000, /* R241 */
+ 0x0000, /* R242 */
+ 0x0004, /* R243 */
+ 0x0300, /* R244 */
+ 0x0000, /* R245 */
+ 0x0200, /* R246 */
+ 0x0000, /* R247 */
+ 0x1000, /* R248 - DCDC1 Test Controls */
+ 0x1000, /* R249 */
+ 0x1000, /* R250 - DCDC3 Test Controls */
+ 0x1000, /* R251 - DCDC4 Test Controls */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_0
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8352_mode0_defaults[] = {
+ 0x6143, /* R0 - Reset/ID */
+ 0x0000, /* R1 - ID */
+ 0x0002, /* R2 - Revision */
+ 0x1C02, /* R3 - System Control 1 */
+ 0x0004, /* R4 - System Control 2 */
+ 0x0000, /* R5 - System Hibernate */
+ 0x8A00, /* R6 - Interface Control */
+ 0x0000, /* R7 */
+ 0x8000, /* R8 - Power mgmt (1) */
+ 0x0000, /* R9 - Power mgmt (2) */
+ 0x0000, /* R10 - Power mgmt (3) */
+ 0x2000, /* R11 - Power mgmt (4) */
+ 0x0E00, /* R12 - Power mgmt (5) */
+ 0x0000, /* R13 - Power mgmt (6) */
+ 0x0000, /* R14 - Power mgmt (7) */
+ 0x0000, /* R15 */
+ 0x0000, /* R16 - RTC Seconds/Minutes */
+ 0x0100, /* R17 - RTC Hours/Day */
+ 0x0101, /* R18 - RTC Date/Month */
+ 0x1400, /* R19 - RTC Year */
+ 0x0000, /* R20 - Alarm Seconds/Minutes */
+ 0x0000, /* R21 - Alarm Hours/Day */
+ 0x0000, /* R22 - Alarm Date/Month */
+ 0x0320, /* R23 - RTC Time Control */
+ 0x0000, /* R24 - System Interrupts */
+ 0x0000, /* R25 - Interrupt Status 1 */
+ 0x0000, /* R26 - Interrupt Status 2 */
+ 0x0000, /* R27 */
+ 0x0000, /* R28 - Under Voltage Interrupt status */
+ 0x0000, /* R29 - Over Current Interrupt status */
+ 0x0000, /* R30 - GPIO Interrupt Status */
+ 0x0000, /* R31 - Comparator Interrupt Status */
+ 0x3FFF, /* R32 - System Interrupts Mask */
+ 0x0000, /* R33 - Interrupt Status 1 Mask */
+ 0x0000, /* R34 - Interrupt Status 2 Mask */
+ 0x0000, /* R35 */
+ 0x0000, /* R36 - Under Voltage Interrupt status Mask */
+ 0x0000, /* R37 - Over Current Interrupt status Mask */
+ 0x0000, /* R38 - GPIO Interrupt Status Mask */
+ 0x0000, /* R39 - Comparator Interrupt Status Mask */
+ 0x0040, /* R40 - Clock Control 1 */
+ 0x0000, /* R41 - Clock Control 2 */
+ 0x3A00, /* R42 - FLL Control 1 */
+ 0x7086, /* R43 - FLL Control 2 */
+ 0xC226, /* R44 - FLL Control 3 */
+ 0x0000, /* R45 - FLL Control 4 */
+ 0x0000, /* R46 */
+ 0x0000, /* R47 */
+ 0x0000, /* R48 - DAC Control */
+ 0x0000, /* R49 */
+ 0x00C0, /* R50 - DAC Digital Volume L */
+ 0x00C0, /* R51 - DAC Digital Volume R */
+ 0x0000, /* R52 */
+ 0x0040, /* R53 - DAC LR Rate */
+ 0x0000, /* R54 - DAC Clock Control */
+ 0x0000, /* R55 */
+ 0x0000, /* R56 */
+ 0x0000, /* R57 */
+ 0x4000, /* R58 - DAC Mute */
+ 0x0000, /* R59 - DAC Mute Volume */
+ 0x0000, /* R60 - DAC Side */
+ 0x0000, /* R61 */
+ 0x0000, /* R62 */
+ 0x0000, /* R63 */
+ 0x8000, /* R64 - ADC Control */
+ 0x0000, /* R65 */
+ 0x00C0, /* R66 - ADC Digital Volume L */
+ 0x00C0, /* R67 - ADC Digital Volume R */
+ 0x0000, /* R68 - ADC Divider */
+ 0x0000, /* R69 */
+ 0x0040, /* R70 - ADC LR Rate */
+ 0x0000, /* R71 */
+ 0x0303, /* R72 - Input Control */
+ 0x0000, /* R73 - IN3 Input Control */
+ 0x0000, /* R74 - Mic Bias Control */
+ 0x0000, /* R75 */
+ 0x0000, /* R76 - Output Control */
+ 0x0000, /* R77 - Jack Detect */
+ 0x0000, /* R78 - Anti Pop Control */
+ 0x0000, /* R79 */
+ 0x0040, /* R80 - Left Input Volume */
+ 0x0040, /* R81 - Right Input Volume */
+ 0x0000, /* R82 */
+ 0x0000, /* R83 */
+ 0x0000, /* R84 */
+ 0x0000, /* R85 */
+ 0x0000, /* R86 */
+ 0x0000, /* R87 */
+ 0x0800, /* R88 - Left Mixer Control */
+ 0x1000, /* R89 - Right Mixer Control */
+ 0x0000, /* R90 */
+ 0x0000, /* R91 */
+ 0x0000, /* R92 - OUT3 Mixer Control */
+ 0x0000, /* R93 - OUT4 Mixer Control */
+ 0x0000, /* R94 */
+ 0x0000, /* R95 */
+ 0x0000, /* R96 - Output Left Mixer Volume */
+ 0x0000, /* R97 - Output Right Mixer Volume */
+ 0x0000, /* R98 - Input Mixer Volume L */
+ 0x0000, /* R99 - Input Mixer Volume R */
+ 0x0000, /* R100 - Input Mixer Volume */
+ 0x0000, /* R101 */
+ 0x0000, /* R102 */
+ 0x0000, /* R103 */
+ 0x00E4, /* R104 - OUT1L Volume */
+ 0x00E4, /* R105 - OUT1R Volume */
+ 0x00E4, /* R106 - OUT2L Volume */
+ 0x02E4, /* R107 - OUT2R Volume */
+ 0x0000, /* R108 */
+ 0x0000, /* R109 */
+ 0x0000, /* R110 */
+ 0x0000, /* R111 - BEEP Volume */
+ 0x0A00, /* R112 - AI Formating */
+ 0x0000, /* R113 - ADC DAC COMP */
+ 0x0020, /* R114 - AI ADC Control */
+ 0x0020, /* R115 - AI DAC Control */
+ 0x0000, /* R116 */
+ 0x0000, /* R117 */
+ 0x0000, /* R118 */
+ 0x0000, /* R119 */
+ 0x0000, /* R120 */
+ 0x0000, /* R121 */
+ 0x0000, /* R122 */
+ 0x0000, /* R123 */
+ 0x0000, /* R124 */
+ 0x0000, /* R125 */
+ 0x0000, /* R126 */
+ 0x0000, /* R127 */
+ 0x1FFF, /* R128 - GPIO Debounce */
+ 0x0000, /* R129 - GPIO Pin pull up Control */
+ 0x0000, /* R130 - GPIO Pull down Control */
+ 0x0000, /* R131 - GPIO Interrupt Mode */
+ 0x0000, /* R132 */
+ 0x0000, /* R133 - GPIO Control */
+ 0x0FFC, /* R134 - GPIO Configuration (i/o) */
+ 0x0FFC, /* R135 - GPIO Pin Polarity / Type */
+ 0x0000, /* R136 */
+ 0x0000, /* R137 */
+ 0x0000, /* R138 */
+ 0x0000, /* R139 */
+ 0x0013, /* R140 - GPIO Function Select 1 */
+ 0x0000, /* R141 - GPIO Function Select 2 */
+ 0x0000, /* R142 - GPIO Function Select 3 */
+ 0x0003, /* R143 - GPIO Function Select 4 */
+ 0x0000, /* R144 - Digitiser Control (1) */
+ 0x0002, /* R145 - Digitiser Control (2) */
+ 0x0000, /* R146 */
+ 0x0000, /* R147 */
+ 0x0000, /* R148 */
+ 0x0000, /* R149 */
+ 0x0000, /* R150 */
+ 0x0000, /* R151 */
+ 0x7000, /* R152 - AUX1 Readback */
+ 0x7000, /* R153 - AUX2 Readback */
+ 0x7000, /* R154 - AUX3 Readback */
+ 0x7000, /* R155 - AUX4 Readback */
+ 0x0000, /* R156 - USB Voltage Readback */
+ 0x0000, /* R157 - LINE Voltage Readback */
+ 0x0000, /* R158 - BATT Voltage Readback */
+ 0x0000, /* R159 - Chip Temp Readback */
+ 0x0000, /* R160 */
+ 0x0000, /* R161 */
+ 0x0000, /* R162 */
+ 0x0000, /* R163 - Generic Comparator Control */
+ 0x0000, /* R164 - Generic comparator 1 */
+ 0x0000, /* R165 - Generic comparator 2 */
+ 0x0000, /* R166 - Generic comparator 3 */
+ 0x0000, /* R167 - Generic comparator 4 */
+ 0xA00F, /* R168 - Battery Charger Control 1 */
+ 0x0B06, /* R169 - Battery Charger Control 2 */
+ 0x0000, /* R170 - Battery Charger Control 3 */
+ 0x0000, /* R171 */
+ 0x0000, /* R172 - Current Sink Driver A */
+ 0x0000, /* R173 - CSA Flash control */
+ 0x0000, /* R174 - Current Sink Driver B */
+ 0x0000, /* R175 - CSB Flash control */
+ 0x0000, /* R176 - DCDC/LDO requested */
+ 0x032D, /* R177 - DCDC Active options */
+ 0x0000, /* R178 - DCDC Sleep options */
+ 0x0025, /* R179 - Power-check comparator */
+ 0x000E, /* R180 - DCDC1 Control */
+ 0x0000, /* R181 - DCDC1 Timeouts */
+ 0x1006, /* R182 - DCDC1 Low Power */
+ 0x0018, /* R183 - DCDC2 Control */
+ 0x0000, /* R184 - DCDC2 Timeouts */
+ 0x0000, /* R185 */
+ 0x0000, /* R186 - DCDC3 Control */
+ 0x0000, /* R187 - DCDC3 Timeouts */
+ 0x0006, /* R188 - DCDC3 Low Power */
+ 0x0000, /* R189 - DCDC4 Control */
+ 0x0000, /* R190 - DCDC4 Timeouts */
+ 0x0006, /* R191 - DCDC4 Low Power */
+ 0x0008, /* R192 - DCDC5 Control */
+ 0x0000, /* R193 - DCDC5 Timeouts */
+ 0x0000, /* R194 */
+ 0x0000, /* R195 - DCDC6 Control */
+ 0x0000, /* R196 - DCDC6 Timeouts */
+ 0x0006, /* R197 - DCDC6 Low Power */
+ 0x0000, /* R198 */
+ 0x0003, /* R199 - Limit Switch Control */
+ 0x001C, /* R200 - LDO1 Control */
+ 0x0000, /* R201 - LDO1 Timeouts */
+ 0x001C, /* R202 - LDO1 Low Power */
+ 0x001B, /* R203 - LDO2 Control */
+ 0x0000, /* R204 - LDO2 Timeouts */
+ 0x001C, /* R205 - LDO2 Low Power */
+ 0x001B, /* R206 - LDO3 Control */
+ 0x0000, /* R207 - LDO3 Timeouts */
+ 0x001C, /* R208 - LDO3 Low Power */
+ 0x001B, /* R209 - LDO4 Control */
+ 0x0000, /* R210 - LDO4 Timeouts */
+ 0x001C, /* R211 - LDO4 Low Power */
+ 0x0000, /* R212 */
+ 0x0000, /* R213 */
+ 0x0000, /* R214 */
+ 0x0000, /* R215 - VCC_FAULT Masks */
+ 0x001F, /* R216 - Main Bandgap Control */
+ 0x0000, /* R217 - OSC Control */
+ 0x9000, /* R218 - RTC Tick Control */
+ 0x0000, /* R219 - Security1 */
+ 0x4000, /* R220 */
+ 0x0000, /* R221 */
+ 0x0000, /* R222 */
+ 0x0000, /* R223 */
+ 0x0000, /* R224 - Signal overrides */
+ 0x0000, /* R225 - DCDC/LDO status */
+ 0x0000, /* R226 - Charger Overides/status */
+ 0x0000, /* R227 - misc overrides */
+ 0x0000, /* R228 - Supply overrides/status 1 */
+ 0x0000, /* R229 - Supply overrides/status 2 */
+ 0xE000, /* R230 - GPIO Pin Status */
+ 0x0000, /* R231 - comparotor overrides */
+ 0x0000, /* R232 */
+ 0x0000, /* R233 - State Machine status */
+ 0x1200, /* R234 */
+ 0x0000, /* R235 */
+ 0x8000, /* R236 */
+ 0x0000, /* R237 */
+ 0x0000, /* R238 */
+ 0x0000, /* R239 */
+ 0x0003, /* R240 */
+ 0x0000, /* R241 */
+ 0x0000, /* R242 */
+ 0x0004, /* R243 */
+ 0x0300, /* R244 */
+ 0x0000, /* R245 */
+ 0x0200, /* R246 */
+ 0x0000, /* R247 */
+ 0x1000, /* R248 - DCDC1 Test Controls */
+ 0x5000, /* R249 */
+ 0x1000, /* R250 - DCDC3 Test Controls */
+ 0x1000, /* R251 - DCDC4 Test Controls */
+ 0x5100, /* R252 */
+ 0x1000, /* R253 - DCDC6 Test Controls */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_1
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8352_mode1_defaults[] = {
+ 0x6143, /* R0 - Reset/ID */
+ 0x0000, /* R1 - ID */
+ 0x0002, /* R2 - Revision */
+ 0x1C02, /* R3 - System Control 1 */
+ 0x0204, /* R4 - System Control 2 */
+ 0x0000, /* R5 - System Hibernate */
+ 0x8A00, /* R6 - Interface Control */
+ 0x0000, /* R7 */
+ 0x8000, /* R8 - Power mgmt (1) */
+ 0x0000, /* R9 - Power mgmt (2) */
+ 0x0000, /* R10 - Power mgmt (3) */
+ 0x2000, /* R11 - Power mgmt (4) */
+ 0x0E00, /* R12 - Power mgmt (5) */
+ 0x0000, /* R13 - Power mgmt (6) */
+ 0x0000, /* R14 - Power mgmt (7) */
+ 0x0000, /* R15 */
+ 0x0000, /* R16 - RTC Seconds/Minutes */
+ 0x0100, /* R17 - RTC Hours/Day */
+ 0x0101, /* R18 - RTC Date/Month */
+ 0x1400, /* R19 - RTC Year */
+ 0x0000, /* R20 - Alarm Seconds/Minutes */
+ 0x0000, /* R21 - Alarm Hours/Day */
+ 0x0000, /* R22 - Alarm Date/Month */
+ 0x0320, /* R23 - RTC Time Control */
+ 0x0000, /* R24 - System Interrupts */
+ 0x0000, /* R25 - Interrupt Status 1 */
+ 0x0000, /* R26 - Interrupt Status 2 */
+ 0x0000, /* R27 */
+ 0x0000, /* R28 - Under Voltage Interrupt status */
+ 0x0000, /* R29 - Over Current Interrupt status */
+ 0x0000, /* R30 - GPIO Interrupt Status */
+ 0x0000, /* R31 - Comparator Interrupt Status */
+ 0x3FFF, /* R32 - System Interrupts Mask */
+ 0x0000, /* R33 - Interrupt Status 1 Mask */
+ 0x0000, /* R34 - Interrupt Status 2 Mask */
+ 0x0000, /* R35 */
+ 0x0000, /* R36 - Under Voltage Interrupt status Mask */
+ 0x0000, /* R37 - Over Current Interrupt status Mask */
+ 0x0000, /* R38 - GPIO Interrupt Status Mask */
+ 0x0000, /* R39 - Comparator Interrupt Status Mask */
+ 0x0040, /* R40 - Clock Control 1 */
+ 0x0000, /* R41 - Clock Control 2 */
+ 0x3A00, /* R42 - FLL Control 1 */
+ 0x7086, /* R43 - FLL Control 2 */
+ 0xC226, /* R44 - FLL Control 3 */
+ 0x0000, /* R45 - FLL Control 4 */
+ 0x0000, /* R46 */
+ 0x0000, /* R47 */
+ 0x0000, /* R48 - DAC Control */
+ 0x0000, /* R49 */
+ 0x00C0, /* R50 - DAC Digital Volume L */
+ 0x00C0, /* R51 - DAC Digital Volume R */
+ 0x0000, /* R52 */
+ 0x0040, /* R53 - DAC LR Rate */
+ 0x0000, /* R54 - DAC Clock Control */
+ 0x0000, /* R55 */
+ 0x0000, /* R56 */
+ 0x0000, /* R57 */
+ 0x4000, /* R58 - DAC Mute */
+ 0x0000, /* R59 - DAC Mute Volume */
+ 0x0000, /* R60 - DAC Side */
+ 0x0000, /* R61 */
+ 0x0000, /* R62 */
+ 0x0000, /* R63 */
+ 0x8000, /* R64 - ADC Control */
+ 0x0000, /* R65 */
+ 0x00C0, /* R66 - ADC Digital Volume L */
+ 0x00C0, /* R67 - ADC Digital Volume R */
+ 0x0000, /* R68 - ADC Divider */
+ 0x0000, /* R69 */
+ 0x0040, /* R70 - ADC LR Rate */
+ 0x0000, /* R71 */
+ 0x0303, /* R72 - Input Control */
+ 0x0000, /* R73 - IN3 Input Control */
+ 0x0000, /* R74 - Mic Bias Control */
+ 0x0000, /* R75 */
+ 0x0000, /* R76 - Output Control */
+ 0x0000, /* R77 - Jack Detect */
+ 0x0000, /* R78 - Anti Pop Control */
+ 0x0000, /* R79 */
+ 0x0040, /* R80 - Left Input Volume */
+ 0x0040, /* R81 - Right Input Volume */
+ 0x0000, /* R82 */
+ 0x0000, /* R83 */
+ 0x0000, /* R84 */
+ 0x0000, /* R85 */
+ 0x0000, /* R86 */
+ 0x0000, /* R87 */
+ 0x0800, /* R88 - Left Mixer Control */
+ 0x1000, /* R89 - Right Mixer Control */
+ 0x0000, /* R90 */
+ 0x0000, /* R91 */
+ 0x0000, /* R92 - OUT3 Mixer Control */
+ 0x0000, /* R93 - OUT4 Mixer Control */
+ 0x0000, /* R94 */
+ 0x0000, /* R95 */
+ 0x0000, /* R96 - Output Left Mixer Volume */
+ 0x0000, /* R97 - Output Right Mixer Volume */
+ 0x0000, /* R98 - Input Mixer Volume L */
+ 0x0000, /* R99 - Input Mixer Volume R */
+ 0x0000, /* R100 - Input Mixer Volume */
+ 0x0000, /* R101 */
+ 0x0000, /* R102 */
+ 0x0000, /* R103 */
+ 0x00E4, /* R104 - OUT1L Volume */
+ 0x00E4, /* R105 - OUT1R Volume */
+ 0x00E4, /* R106 - OUT2L Volume */
+ 0x02E4, /* R107 - OUT2R Volume */
+ 0x0000, /* R108 */
+ 0x0000, /* R109 */
+ 0x0000, /* R110 */
+ 0x0000, /* R111 - BEEP Volume */
+ 0x0A00, /* R112 - AI Formating */
+ 0x0000, /* R113 - ADC DAC COMP */
+ 0x0020, /* R114 - AI ADC Control */
+ 0x0020, /* R115 - AI DAC Control */
+ 0x0000, /* R116 */
+ 0x0000, /* R117 */
+ 0x0000, /* R118 */
+ 0x0000, /* R119 */
+ 0x0000, /* R120 */
+ 0x0000, /* R121 */
+ 0x0000, /* R122 */
+ 0x0000, /* R123 */
+ 0x0000, /* R124 */
+ 0x0000, /* R125 */
+ 0x0000, /* R126 */
+ 0x0000, /* R127 */
+ 0x1FFF, /* R128 - GPIO Debounce */
+ 0x0000, /* R129 - GPIO Pin pull up Control */
+ 0x0000, /* R130 - GPIO Pull down Control */
+ 0x0000, /* R131 - GPIO Interrupt Mode */
+ 0x0000, /* R132 */
+ 0x0000, /* R133 - GPIO Control */
+ 0x0BFB, /* R134 - GPIO Configuration (i/o) */
+ 0x0FFF, /* R135 - GPIO Pin Polarity / Type */
+ 0x0000, /* R136 */
+ 0x0000, /* R137 */
+ 0x0000, /* R138 */
+ 0x0000, /* R139 */
+ 0x0300, /* R140 - GPIO Function Select 1 */
+ 0x0000, /* R141 - GPIO Function Select 2 */
+ 0x2300, /* R142 - GPIO Function Select 3 */
+ 0x0003, /* R143 - GPIO Function Select 4 */
+ 0x0000, /* R144 - Digitiser Control (1) */
+ 0x0002, /* R145 - Digitiser Control (2) */
+ 0x0000, /* R146 */
+ 0x0000, /* R147 */
+ 0x0000, /* R148 */
+ 0x0000, /* R149 */
+ 0x0000, /* R150 */
+ 0x0000, /* R151 */
+ 0x7000, /* R152 - AUX1 Readback */
+ 0x7000, /* R153 - AUX2 Readback */
+ 0x7000, /* R154 - AUX3 Readback */
+ 0x7000, /* R155 - AUX4 Readback */
+ 0x0000, /* R156 - USB Voltage Readback */
+ 0x0000, /* R157 - LINE Voltage Readback */
+ 0x0000, /* R158 - BATT Voltage Readback */
+ 0x0000, /* R159 - Chip Temp Readback */
+ 0x0000, /* R160 */
+ 0x0000, /* R161 */
+ 0x0000, /* R162 */
+ 0x0000, /* R163 - Generic Comparator Control */
+ 0x0000, /* R164 - Generic comparator 1 */
+ 0x0000, /* R165 - Generic comparator 2 */
+ 0x0000, /* R166 - Generic comparator 3 */
+ 0x0000, /* R167 - Generic comparator 4 */
+ 0xA00F, /* R168 - Battery Charger Control 1 */
+ 0x0B06, /* R169 - Battery Charger Control 2 */
+ 0x0000, /* R170 - Battery Charger Control 3 */
+ 0x0000, /* R171 */
+ 0x0000, /* R172 - Current Sink Driver A */
+ 0x0000, /* R173 - CSA Flash control */
+ 0x0000, /* R174 - Current Sink Driver B */
+ 0x0000, /* R175 - CSB Flash control */
+ 0x0000, /* R176 - DCDC/LDO requested */
+ 0x032D, /* R177 - DCDC Active options */
+ 0x0000, /* R178 - DCDC Sleep options */
+ 0x0025, /* R179 - Power-check comparator */
+ 0x0062, /* R180 - DCDC1 Control */
+ 0x0400, /* R181 - DCDC1 Timeouts */
+ 0x1006, /* R182 - DCDC1 Low Power */
+ 0x0018, /* R183 - DCDC2 Control */
+ 0x0000, /* R184 - DCDC2 Timeouts */
+ 0x0000, /* R185 */
+ 0x0006, /* R186 - DCDC3 Control */
+ 0x0800, /* R187 - DCDC3 Timeouts */
+ 0x0006, /* R188 - DCDC3 Low Power */
+ 0x0006, /* R189 - DCDC4 Control */
+ 0x0C00, /* R190 - DCDC4 Timeouts */
+ 0x0006, /* R191 - DCDC4 Low Power */
+ 0x0008, /* R192 - DCDC5 Control */
+ 0x0000, /* R193 - DCDC5 Timeouts */
+ 0x0000, /* R194 */
+ 0x0026, /* R195 - DCDC6 Control */
+ 0x1000, /* R196 - DCDC6 Timeouts */
+ 0x0006, /* R197 - DCDC6 Low Power */
+ 0x0000, /* R198 */
+ 0x0003, /* R199 - Limit Switch Control */
+ 0x0002, /* R200 - LDO1 Control */
+ 0x0000, /* R201 - LDO1 Timeouts */
+ 0x001C, /* R202 - LDO1 Low Power */
+ 0x001A, /* R203 - LDO2 Control */
+ 0x0000, /* R204 - LDO2 Timeouts */
+ 0x001C, /* R205 - LDO2 Low Power */
+ 0x001F, /* R206 - LDO3 Control */
+ 0x0000, /* R207 - LDO3 Timeouts */
+ 0x001C, /* R208 - LDO3 Low Power */
+ 0x001F, /* R209 - LDO4 Control */
+ 0x0000, /* R210 - LDO4 Timeouts */
+ 0x001C, /* R211 - LDO4 Low Power */
+ 0x0000, /* R212 */
+ 0x0000, /* R213 */
+ 0x0000, /* R214 */
+ 0x0000, /* R215 - VCC_FAULT Masks */
+ 0x001F, /* R216 - Main Bandgap Control */
+ 0x0000, /* R217 - OSC Control */
+ 0x9000, /* R218 - RTC Tick Control */
+ 0x0000, /* R219 - Security1 */
+ 0x4000, /* R220 */
+ 0x0000, /* R221 */
+ 0x0000, /* R222 */
+ 0x0000, /* R223 */
+ 0x0000, /* R224 - Signal overrides */
+ 0x0000, /* R225 - DCDC/LDO status */
+ 0x0000, /* R226 - Charger Overides/status */
+ 0x0000, /* R227 - misc overrides */
+ 0x0000, /* R228 - Supply overrides/status 1 */
+ 0x0000, /* R229 - Supply overrides/status 2 */
+ 0xE000, /* R230 - GPIO Pin Status */
+ 0x0000, /* R231 - comparotor overrides */
+ 0x0000, /* R232 */
+ 0x0000, /* R233 - State Machine status */
+ 0x1200, /* R234 */
+ 0x0000, /* R235 */
+ 0x8000, /* R236 */
+ 0x0000, /* R237 */
+ 0x0000, /* R238 */
+ 0x0000, /* R239 */
+ 0x0003, /* R240 */
+ 0x0000, /* R241 */
+ 0x0000, /* R242 */
+ 0x0004, /* R243 */
+ 0x0300, /* R244 */
+ 0x0000, /* R245 */
+ 0x0200, /* R246 */
+ 0x0000, /* R247 */
+ 0x1000, /* R248 - DCDC1 Test Controls */
+ 0x5000, /* R249 */
+ 0x1000, /* R250 - DCDC3 Test Controls */
+ 0x1000, /* R251 - DCDC4 Test Controls */
+ 0x5100, /* R252 */
+ 0x1000, /* R253 - DCDC6 Test Controls */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_2
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8352_mode2_defaults[] = {
+ 0x6143, /* R0 - Reset/ID */
+ 0x0000, /* R1 - ID */
+ 0x0002, /* R2 - Revision */
+ 0x1C02, /* R3 - System Control 1 */
+ 0x0204, /* R4 - System Control 2 */
+ 0x0000, /* R5 - System Hibernate */
+ 0x8A00, /* R6 - Interface Control */
+ 0x0000, /* R7 */
+ 0x8000, /* R8 - Power mgmt (1) */
+ 0x0000, /* R9 - Power mgmt (2) */
+ 0x0000, /* R10 - Power mgmt (3) */
+ 0x2000, /* R11 - Power mgmt (4) */
+ 0x0E00, /* R12 - Power mgmt (5) */
+ 0x0000, /* R13 - Power mgmt (6) */
+ 0x0000, /* R14 - Power mgmt (7) */
+ 0x0000, /* R15 */
+ 0x0000, /* R16 - RTC Seconds/Minutes */
+ 0x0100, /* R17 - RTC Hours/Day */
+ 0x0101, /* R18 - RTC Date/Month */
+ 0x1400, /* R19 - RTC Year */
+ 0x0000, /* R20 - Alarm Seconds/Minutes */
+ 0x0000, /* R21 - Alarm Hours/Day */
+ 0x0000, /* R22 - Alarm Date/Month */
+ 0x0320, /* R23 - RTC Time Control */
+ 0x0000, /* R24 - System Interrupts */
+ 0x0000, /* R25 - Interrupt Status 1 */
+ 0x0000, /* R26 - Interrupt Status 2 */
+ 0x0000, /* R27 */
+ 0x0000, /* R28 - Under Voltage Interrupt status */
+ 0x0000, /* R29 - Over Current Interrupt status */
+ 0x0000, /* R30 - GPIO Interrupt Status */
+ 0x0000, /* R31 - Comparator Interrupt Status */
+ 0x3FFF, /* R32 - System Interrupts Mask */
+ 0x0000, /* R33 - Interrupt Status 1 Mask */
+ 0x0000, /* R34 - Interrupt Status 2 Mask */
+ 0x0000, /* R35 */
+ 0x0000, /* R36 - Under Voltage Interrupt status Mask */
+ 0x0000, /* R37 - Over Current Interrupt status Mask */
+ 0x0000, /* R38 - GPIO Interrupt Status Mask */
+ 0x0000, /* R39 - Comparator Interrupt Status Mask */
+ 0x0040, /* R40 - Clock Control 1 */
+ 0x0000, /* R41 - Clock Control 2 */
+ 0x3A00, /* R42 - FLL Control 1 */
+ 0x7086, /* R43 - FLL Control 2 */
+ 0xC226, /* R44 - FLL Control 3 */
+ 0x0000, /* R45 - FLL Control 4 */
+ 0x0000, /* R46 */
+ 0x0000, /* R47 */
+ 0x0000, /* R48 - DAC Control */
+ 0x0000, /* R49 */
+ 0x00C0, /* R50 - DAC Digital Volume L */
+ 0x00C0, /* R51 - DAC Digital Volume R */
+ 0x0000, /* R52 */
+ 0x0040, /* R53 - DAC LR Rate */
+ 0x0000, /* R54 - DAC Clock Control */
+ 0x0000, /* R55 */
+ 0x0000, /* R56 */
+ 0x0000, /* R57 */
+ 0x4000, /* R58 - DAC Mute */
+ 0x0000, /* R59 - DAC Mute Volume */
+ 0x0000, /* R60 - DAC Side */
+ 0x0000, /* R61 */
+ 0x0000, /* R62 */
+ 0x0000, /* R63 */
+ 0x8000, /* R64 - ADC Control */
+ 0x0000, /* R65 */
+ 0x00C0, /* R66 - ADC Digital Volume L */
+ 0x00C0, /* R67 - ADC Digital Volume R */
+ 0x0000, /* R68 - ADC Divider */
+ 0x0000, /* R69 */
+ 0x0040, /* R70 - ADC LR Rate */
+ 0x0000, /* R71 */
+ 0x0303, /* R72 - Input Control */
+ 0x0000, /* R73 - IN3 Input Control */
+ 0x0000, /* R74 - Mic Bias Control */
+ 0x0000, /* R75 */
+ 0x0000, /* R76 - Output Control */
+ 0x0000, /* R77 - Jack Detect */
+ 0x0000, /* R78 - Anti Pop Control */
+ 0x0000, /* R79 */
+ 0x0040, /* R80 - Left Input Volume */
+ 0x0040, /* R81 - Right Input Volume */
+ 0x0000, /* R82 */
+ 0x0000, /* R83 */
+ 0x0000, /* R84 */
+ 0x0000, /* R85 */
+ 0x0000, /* R86 */
+ 0x0000, /* R87 */
+ 0x0800, /* R88 - Left Mixer Control */
+ 0x1000, /* R89 - Right Mixer Control */
+ 0x0000, /* R90 */
+ 0x0000, /* R91 */
+ 0x0000, /* R92 - OUT3 Mixer Control */
+ 0x0000, /* R93 - OUT4 Mixer Control */
+ 0x0000, /* R94 */
+ 0x0000, /* R95 */
+ 0x0000, /* R96 - Output Left Mixer Volume */
+ 0x0000, /* R97 - Output Right Mixer Volume */
+ 0x0000, /* R98 - Input Mixer Volume L */
+ 0x0000, /* R99 - Input Mixer Volume R */
+ 0x0000, /* R100 - Input Mixer Volume */
+ 0x0000, /* R101 */
+ 0x0000, /* R102 */
+ 0x0000, /* R103 */
+ 0x00E4, /* R104 - OUT1L Volume */
+ 0x00E4, /* R105 - OUT1R Volume */
+ 0x00E4, /* R106 - OUT2L Volume */
+ 0x02E4, /* R107 - OUT2R Volume */
+ 0x0000, /* R108 */
+ 0x0000, /* R109 */
+ 0x0000, /* R110 */
+ 0x0000, /* R111 - BEEP Volume */
+ 0x0A00, /* R112 - AI Formating */
+ 0x0000, /* R113 - ADC DAC COMP */
+ 0x0020, /* R114 - AI ADC Control */
+ 0x0020, /* R115 - AI DAC Control */
+ 0x0000, /* R116 */
+ 0x0000, /* R117 */
+ 0x0000, /* R118 */
+ 0x0000, /* R119 */
+ 0x0000, /* R120 */
+ 0x0000, /* R121 */
+ 0x0000, /* R122 */
+ 0x0000, /* R123 */
+ 0x0000, /* R124 */
+ 0x0000, /* R125 */
+ 0x0000, /* R126 */
+ 0x0000, /* R127 */
+ 0x1FFF, /* R128 - GPIO Debounce */
+ 0x0000, /* R129 - GPIO Pin pull up Control */
+ 0x0110, /* R130 - GPIO Pull down Control */
+ 0x0000, /* R131 - GPIO Interrupt Mode */
+ 0x0000, /* R132 */
+ 0x0000, /* R133 - GPIO Control */
+ 0x09DA, /* R134 - GPIO Configuration (i/o) */
+ 0x0DD6, /* R135 - GPIO Pin Polarity / Type */
+ 0x0000, /* R136 */
+ 0x0000, /* R137 */
+ 0x0000, /* R138 */
+ 0x0000, /* R139 */
+ 0x1310, /* R140 - GPIO Function Select 1 */
+ 0x0033, /* R141 - GPIO Function Select 2 */
+ 0x2000, /* R142 - GPIO Function Select 3 */
+ 0x0000, /* R143 - GPIO Function Select 4 */
+ 0x0000, /* R144 - Digitiser Control (1) */
+ 0x0002, /* R145 - Digitiser Control (2) */
+ 0x0000, /* R146 */
+ 0x0000, /* R147 */
+ 0x0000, /* R148 */
+ 0x0000, /* R149 */
+ 0x0000, /* R150 */
+ 0x0000, /* R151 */
+ 0x7000, /* R152 - AUX1 Readback */
+ 0x7000, /* R153 - AUX2 Readback */
+ 0x7000, /* R154 - AUX3 Readback */
+ 0x7000, /* R155 - AUX4 Readback */
+ 0x0000, /* R156 - USB Voltage Readback */
+ 0x0000, /* R157 - LINE Voltage Readback */
+ 0x0000, /* R158 - BATT Voltage Readback */
+ 0x0000, /* R159 - Chip Temp Readback */
+ 0x0000, /* R160 */
+ 0x0000, /* R161 */
+ 0x0000, /* R162 */
+ 0x0000, /* R163 - Generic Comparator Control */
+ 0x0000, /* R164 - Generic comparator 1 */
+ 0x0000, /* R165 - Generic comparator 2 */
+ 0x0000, /* R166 - Generic comparator 3 */
+ 0x0000, /* R167 - Generic comparator 4 */
+ 0xA00F, /* R168 - Battery Charger Control 1 */
+ 0x0B06, /* R169 - Battery Charger Control 2 */
+ 0x0000, /* R170 - Battery Charger Control 3 */
+ 0x0000, /* R171 */
+ 0x0000, /* R172 - Current Sink Driver A */
+ 0x0000, /* R173 - CSA Flash control */
+ 0x0000, /* R174 - Current Sink Driver B */
+ 0x0000, /* R175 - CSB Flash control */
+ 0x0000, /* R176 - DCDC/LDO requested */
+ 0x032D, /* R177 - DCDC Active options */
+ 0x0000, /* R178 - DCDC Sleep options */
+ 0x0025, /* R179 - Power-check comparator */
+ 0x000E, /* R180 - DCDC1 Control */
+ 0x0800, /* R181 - DCDC1 Timeouts */
+ 0x1006, /* R182 - DCDC1 Low Power */
+ 0x0018, /* R183 - DCDC2 Control */
+ 0x0000, /* R184 - DCDC2 Timeouts */
+ 0x0000, /* R185 */
+ 0x0056, /* R186 - DCDC3 Control */
+ 0x1800, /* R187 - DCDC3 Timeouts */
+ 0x0006, /* R188 - DCDC3 Low Power */
+ 0x000E, /* R189 - DCDC4 Control */
+ 0x1000, /* R190 - DCDC4 Timeouts */
+ 0x0006, /* R191 - DCDC4 Low Power */
+ 0x0008, /* R192 - DCDC5 Control */
+ 0x0000, /* R193 - DCDC5 Timeouts */
+ 0x0000, /* R194 */
+ 0x0026, /* R195 - DCDC6 Control */
+ 0x0C00, /* R196 - DCDC6 Timeouts */
+ 0x0006, /* R197 - DCDC6 Low Power */
+ 0x0000, /* R198 */
+ 0x0003, /* R199 - Limit Switch Control */
+ 0x001C, /* R200 - LDO1 Control */
+ 0x0000, /* R201 - LDO1 Timeouts */
+ 0x001C, /* R202 - LDO1 Low Power */
+ 0x0006, /* R203 - LDO2 Control */
+ 0x0400, /* R204 - LDO2 Timeouts */
+ 0x001C, /* R205 - LDO2 Low Power */
+ 0x001C, /* R206 - LDO3 Control */
+ 0x1400, /* R207 - LDO3 Timeouts */
+ 0x001C, /* R208 - LDO3 Low Power */
+ 0x001A, /* R209 - LDO4 Control */
+ 0x0000, /* R210 - LDO4 Timeouts */
+ 0x001C, /* R211 - LDO4 Low Power */
+ 0x0000, /* R212 */
+ 0x0000, /* R213 */
+ 0x0000, /* R214 */
+ 0x0000, /* R215 - VCC_FAULT Masks */
+ 0x001F, /* R216 - Main Bandgap Control */
+ 0x0000, /* R217 - OSC Control */
+ 0x9000, /* R218 - RTC Tick Control */
+ 0x0000, /* R219 - Security1 */
+ 0x4000, /* R220 */
+ 0x0000, /* R221 */
+ 0x0000, /* R222 */
+ 0x0000, /* R223 */
+ 0x0000, /* R224 - Signal overrides */
+ 0x0000, /* R225 - DCDC/LDO status */
+ 0x0000, /* R226 - Charger Overides/status */
+ 0x0000, /* R227 - misc overrides */
+ 0x0000, /* R228 - Supply overrides/status 1 */
+ 0x0000, /* R229 - Supply overrides/status 2 */
+ 0xE000, /* R230 - GPIO Pin Status */
+ 0x0000, /* R231 - comparotor overrides */
+ 0x0000, /* R232 */
+ 0x0000, /* R233 - State Machine status */
+ 0x1200, /* R234 */
+ 0x0000, /* R235 */
+ 0x8000, /* R236 */
+ 0x0000, /* R237 */
+ 0x0000, /* R238 */
+ 0x0000, /* R239 */
+ 0x0003, /* R240 */
+ 0x0000, /* R241 */
+ 0x0000, /* R242 */
+ 0x0004, /* R243 */
+ 0x0300, /* R244 */
+ 0x0000, /* R245 */
+ 0x0200, /* R246 */
+ 0x0000, /* R247 */
+ 0x1000, /* R248 - DCDC1 Test Controls */
+ 0x5000, /* R249 */
+ 0x1000, /* R250 - DCDC3 Test Controls */
+ 0x1000, /* R251 - DCDC4 Test Controls */
+ 0x5100, /* R252 */
+ 0x1000, /* R253 - DCDC6 Test Controls */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_3
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8352_mode3_defaults[] = {
+ 0x6143, /* R0 - Reset/ID */
+ 0x0000, /* R1 - ID */
+ 0x0002, /* R2 - Revision */
+ 0x1C02, /* R3 - System Control 1 */
+ 0x0204, /* R4 - System Control 2 */
+ 0x0000, /* R5 - System Hibernate */
+ 0x8A00, /* R6 - Interface Control */
+ 0x0000, /* R7 */
+ 0x8000, /* R8 - Power mgmt (1) */
+ 0x0000, /* R9 - Power mgmt (2) */
+ 0x0000, /* R10 - Power mgmt (3) */
+ 0x2000, /* R11 - Power mgmt (4) */
+ 0x0E00, /* R12 - Power mgmt (5) */
+ 0x0000, /* R13 - Power mgmt (6) */
+ 0x0000, /* R14 - Power mgmt (7) */
+ 0x0000, /* R15 */
+ 0x0000, /* R16 - RTC Seconds/Minutes */
+ 0x0100, /* R17 - RTC Hours/Day */
+ 0x0101, /* R18 - RTC Date/Month */
+ 0x1400, /* R19 - RTC Year */
+ 0x0000, /* R20 - Alarm Seconds/Minutes */
+ 0x0000, /* R21 - Alarm Hours/Day */
+ 0x0000, /* R22 - Alarm Date/Month */
+ 0x0320, /* R23 - RTC Time Control */
+ 0x0000, /* R24 - System Interrupts */
+ 0x0000, /* R25 - Interrupt Status 1 */
+ 0x0000, /* R26 - Interrupt Status 2 */
+ 0x0000, /* R27 */
+ 0x0000, /* R28 - Under Voltage Interrupt status */
+ 0x0000, /* R29 - Over Current Interrupt status */
+ 0x0000, /* R30 - GPIO Interrupt Status */
+ 0x0000, /* R31 - Comparator Interrupt Status */
+ 0x3FFF, /* R32 - System Interrupts Mask */
+ 0x0000, /* R33 - Interrupt Status 1 Mask */
+ 0x0000, /* R34 - Interrupt Status 2 Mask */
+ 0x0000, /* R35 */
+ 0x0000, /* R36 - Under Voltage Interrupt status Mask */
+ 0x0000, /* R37 - Over Current Interrupt status Mask */
+ 0x0000, /* R38 - GPIO Interrupt Status Mask */
+ 0x0000, /* R39 - Comparator Interrupt Status Mask */
+ 0x0040, /* R40 - Clock Control 1 */
+ 0x0000, /* R41 - Clock Control 2 */
+ 0x3A00, /* R42 - FLL Control 1 */
+ 0x7086, /* R43 - FLL Control 2 */
+ 0xC226, /* R44 - FLL Control 3 */
+ 0x0000, /* R45 - FLL Control 4 */
+ 0x0000, /* R46 */
+ 0x0000, /* R47 */
+ 0x0000, /* R48 - DAC Control */
+ 0x0000, /* R49 */
+ 0x00C0, /* R50 - DAC Digital Volume L */
+ 0x00C0, /* R51 - DAC Digital Volume R */
+ 0x0000, /* R52 */
+ 0x0040, /* R53 - DAC LR Rate */
+ 0x0000, /* R54 - DAC Clock Control */
+ 0x0000, /* R55 */
+ 0x0000, /* R56 */
+ 0x0000, /* R57 */
+ 0x4000, /* R58 - DAC Mute */
+ 0x0000, /* R59 - DAC Mute Volume */
+ 0x0000, /* R60 - DAC Side */
+ 0x0000, /* R61 */
+ 0x0000, /* R62 */
+ 0x0000, /* R63 */
+ 0x8000, /* R64 - ADC Control */
+ 0x0000, /* R65 */
+ 0x00C0, /* R66 - ADC Digital Volume L */
+ 0x00C0, /* R67 - ADC Digital Volume R */
+ 0x0000, /* R68 - ADC Divider */
+ 0x0000, /* R69 */
+ 0x0040, /* R70 - ADC LR Rate */
+ 0x0000, /* R71 */
+ 0x0303, /* R72 - Input Control */
+ 0x0000, /* R73 - IN3 Input Control */
+ 0x0000, /* R74 - Mic Bias Control */
+ 0x0000, /* R75 */
+ 0x0000, /* R76 - Output Control */
+ 0x0000, /* R77 - Jack Detect */
+ 0x0000, /* R78 - Anti Pop Control */
+ 0x0000, /* R79 */
+ 0x0040, /* R80 - Left Input Volume */
+ 0x0040, /* R81 - Right Input Volume */
+ 0x0000, /* R82 */
+ 0x0000, /* R83 */
+ 0x0000, /* R84 */
+ 0x0000, /* R85 */
+ 0x0000, /* R86 */
+ 0x0000, /* R87 */
+ 0x0800, /* R88 - Left Mixer Control */
+ 0x1000, /* R89 - Right Mixer Control */
+ 0x0000, /* R90 */
+ 0x0000, /* R91 */
+ 0x0000, /* R92 - OUT3 Mixer Control */
+ 0x0000, /* R93 - OUT4 Mixer Control */
+ 0x0000, /* R94 */
+ 0x0000, /* R95 */
+ 0x0000, /* R96 - Output Left Mixer Volume */
+ 0x0000, /* R97 - Output Right Mixer Volume */
+ 0x0000, /* R98 - Input Mixer Volume L */
+ 0x0000, /* R99 - Input Mixer Volume R */
+ 0x0000, /* R100 - Input Mixer Volume */
+ 0x0000, /* R101 */
+ 0x0000, /* R102 */
+ 0x0000, /* R103 */
+ 0x00E4, /* R104 - OUT1L Volume */
+ 0x00E4, /* R105 - OUT1R Volume */
+ 0x00E4, /* R106 - OUT2L Volume */
+ 0x02E4, /* R107 - OUT2R Volume */
+ 0x0000, /* R108 */
+ 0x0000, /* R109 */
+ 0x0000, /* R110 */
+ 0x0000, /* R111 - BEEP Volume */
+ 0x0A00, /* R112 - AI Formating */
+ 0x0000, /* R113 - ADC DAC COMP */
+ 0x0020, /* R114 - AI ADC Control */
+ 0x0020, /* R115 - AI DAC Control */
+ 0x0000, /* R116 */
+ 0x0000, /* R117 */
+ 0x0000, /* R118 */
+ 0x0000, /* R119 */
+ 0x0000, /* R120 */
+ 0x0000, /* R121 */
+ 0x0000, /* R122 */
+ 0x0000, /* R123 */
+ 0x0000, /* R124 */
+ 0x0000, /* R125 */
+ 0x0000, /* R126 */
+ 0x0000, /* R127 */
+ 0x1FFF, /* R128 - GPIO Debounce */
+ 0x0010, /* R129 - GPIO Pin pull up Control */
+ 0x0000, /* R130 - GPIO Pull down Control */
+ 0x0000, /* R131 - GPIO Interrupt Mode */
+ 0x0000, /* R132 */
+ 0x0000, /* R133 - GPIO Control */
+ 0x0BFB, /* R134 - GPIO Configuration (i/o) */
+ 0x0FFD, /* R135 - GPIO Pin Polarity / Type */
+ 0x0000, /* R136 */
+ 0x0000, /* R137 */
+ 0x0000, /* R138 */
+ 0x0000, /* R139 */
+ 0x0310, /* R140 - GPIO Function Select 1 */
+ 0x0001, /* R141 - GPIO Function Select 2 */
+ 0x2300, /* R142 - GPIO Function Select 3 */
+ 0x0003, /* R143 - GPIO Function Select 4 */
+ 0x0000, /* R144 - Digitiser Control (1) */
+ 0x0002, /* R145 - Digitiser Control (2) */
+ 0x0000, /* R146 */
+ 0x0000, /* R147 */
+ 0x0000, /* R148 */
+ 0x0000, /* R149 */
+ 0x0000, /* R150 */
+ 0x0000, /* R151 */
+ 0x7000, /* R152 - AUX1 Readback */
+ 0x7000, /* R153 - AUX2 Readback */
+ 0x7000, /* R154 - AUX3 Readback */
+ 0x7000, /* R155 - AUX4 Readback */
+ 0x0000, /* R156 - USB Voltage Readback */
+ 0x0000, /* R157 - LINE Voltage Readback */
+ 0x0000, /* R158 - BATT Voltage Readback */
+ 0x0000, /* R159 - Chip Temp Readback */
+ 0x0000, /* R160 */
+ 0x0000, /* R161 */
+ 0x0000, /* R162 */
+ 0x0000, /* R163 - Generic Comparator Control */
+ 0x0000, /* R164 - Generic comparator 1 */
+ 0x0000, /* R165 - Generic comparator 2 */
+ 0x0000, /* R166 - Generic comparator 3 */
+ 0x0000, /* R167 - Generic comparator 4 */
+ 0xA00F, /* R168 - Battery Charger Control 1 */
+ 0x0B06, /* R169 - Battery Charger Control 2 */
+ 0x0000, /* R170 - Battery Charger Control 3 */
+ 0x0000, /* R171 */
+ 0x0000, /* R172 - Current Sink Driver A */
+ 0x0000, /* R173 - CSA Flash control */
+ 0x0000, /* R174 - Current Sink Driver B */
+ 0x0000, /* R175 - CSB Flash control */
+ 0x0000, /* R176 - DCDC/LDO requested */
+ 0x032D, /* R177 - DCDC Active options */
+ 0x0000, /* R178 - DCDC Sleep options */
+ 0x0025, /* R179 - Power-check comparator */
+ 0x0006, /* R180 - DCDC1 Control */
+ 0x0400, /* R181 - DCDC1 Timeouts */
+ 0x1006, /* R182 - DCDC1 Low Power */
+ 0x0018, /* R183 - DCDC2 Control */
+ 0x0000, /* R184 - DCDC2 Timeouts */
+ 0x0000, /* R185 */
+ 0x0050, /* R186 - DCDC3 Control */
+ 0x0C00, /* R187 - DCDC3 Timeouts */
+ 0x0006, /* R188 - DCDC3 Low Power */
+ 0x000E, /* R189 - DCDC4 Control */
+ 0x0400, /* R190 - DCDC4 Timeouts */
+ 0x0006, /* R191 - DCDC4 Low Power */
+ 0x0008, /* R192 - DCDC5 Control */
+ 0x0000, /* R193 - DCDC5 Timeouts */
+ 0x0000, /* R194 */
+ 0x0029, /* R195 - DCDC6 Control */
+ 0x0800, /* R196 - DCDC6 Timeouts */
+ 0x0006, /* R197 - DCDC6 Low Power */
+ 0x0000, /* R198 */
+ 0x0003, /* R199 - Limit Switch Control */
+ 0x001D, /* R200 - LDO1 Control */
+ 0x1000, /* R201 - LDO1 Timeouts */
+ 0x001C, /* R202 - LDO1 Low Power */
+ 0x0017, /* R203 - LDO2 Control */
+ 0x1000, /* R204 - LDO2 Timeouts */
+ 0x001C, /* R205 - LDO2 Low Power */
+ 0x0006, /* R206 - LDO3 Control */
+ 0x1000, /* R207 - LDO3 Timeouts */
+ 0x001C, /* R208 - LDO3 Low Power */
+ 0x0010, /* R209 - LDO4 Control */
+ 0x1000, /* R210 - LDO4 Timeouts */
+ 0x001C, /* R211 - LDO4 Low Power */
+ 0x0000, /* R212 */
+ 0x0000, /* R213 */
+ 0x0000, /* R214 */
+ 0x0000, /* R215 - VCC_FAULT Masks */
+ 0x001F, /* R216 - Main Bandgap Control */
+ 0x0000, /* R217 - OSC Control */
+ 0x9000, /* R218 - RTC Tick Control */
+ 0x0000, /* R219 - Security1 */
+ 0x4000, /* R220 */
+ 0x0000, /* R221 */
+ 0x0000, /* R222 */
+ 0x0000, /* R223 */
+ 0x0000, /* R224 - Signal overrides */
+ 0x0000, /* R225 - DCDC/LDO status */
+ 0x0000, /* R226 - Charger Overides/status */
+ 0x0000, /* R227 - misc overrides */
+ 0x0000, /* R228 - Supply overrides/status 1 */
+ 0x0000, /* R229 - Supply overrides/status 2 */
+ 0xE000, /* R230 - GPIO Pin Status */
+ 0x0000, /* R231 - comparotor overrides */
+ 0x0000, /* R232 */
+ 0x0000, /* R233 - State Machine status */
+ 0x1200, /* R234 */
+ 0x0000, /* R235 */
+ 0x8000, /* R236 */
+ 0x0000, /* R237 */
+ 0x0000, /* R238 */
+ 0x0000, /* R239 */
+ 0x0003, /* R240 */
+ 0x0000, /* R241 */
+ 0x0000, /* R242 */
+ 0x0004, /* R243 */
+ 0x0300, /* R244 */
+ 0x0000, /* R245 */
+ 0x0200, /* R246 */
+ 0x0000, /* R247 */
+ 0x1000, /* R248 - DCDC1 Test Controls */
+ 0x5000, /* R249 */
+ 0x1000, /* R250 - DCDC3 Test Controls */
+ 0x1000, /* R251 - DCDC4 Test Controls */
+ 0x5100, /* R252 */
+ 0x1000, /* R253 - DCDC6 Test Controls */
+};
+#endif
+
/* The register defaults for the config mode used must be compiled in but
* due to the impact on kernel size it is possible to disable
*/
@@ -1307,14 +3403,14 @@ const struct wm8350_reg_access wm8350_reg_io_map[] = {
{ 0xFF3F, 0xE03F, 0x0000 }, /* R216 - Main Bandgap Control */
{ 0xEF2F, 0xE02F, 0x0000 }, /* R217 - OSC Control */
{ 0xF3FF, 0xB3FF, 0xc000 }, /* R218 - RTC Tick Control */
- { 0xFFFF, 0xFFFF, 0xFFFF }, /* R219 */
+ { 0xFFFF, 0xFFFF, 0x0000 }, /* R219 - Security */
{ 0x09FF, 0x01FF, 0x0000 }, /* R220 - RAM BIST 1 */
{ 0x0000, 0x0000, 0x0000 }, /* R221 */
{ 0xFFFF, 0xFFFF, 0xFFFF }, /* R222 */
{ 0xFFFF, 0xFFFF, 0xFFFF }, /* R223 */
{ 0x0000, 0x0000, 0x0000 }, /* R224 */
{ 0x8F3F, 0x0000, 0xFFFF }, /* R225 - DCDC/LDO status */
- { 0x0000, 0x0000, 0x0000 }, /* R226 */
+ { 0x0000, 0x0000, 0xFFFF }, /* R226 - Charger status */
{ 0x0000, 0x0000, 0xFFFF }, /* R227 */
{ 0x0000, 0x0000, 0x0000 }, /* R228 */
{ 0x0000, 0x0000, 0x0000 }, /* R229 */
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c
index 6a0cedb5bb8..cf30d06a010 100644
--- a/drivers/mfd/wm8400-core.c
+++ b/drivers/mfd/wm8400-core.c
@@ -15,6 +15,7 @@
#include <linux/bug.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
+#include <linux/mfd/core.h>
#include <linux/mfd/wm8400-private.h>
#include <linux/mfd/wm8400-audio.h>
@@ -239,6 +240,16 @@ void wm8400_reset_codec_reg_cache(struct wm8400 *wm8400)
}
EXPORT_SYMBOL_GPL(wm8400_reset_codec_reg_cache);
+static int wm8400_register_codec(struct wm8400 *wm8400)
+{
+ struct mfd_cell cell = {
+ .name = "wm8400-codec",
+ .driver_data = wm8400,
+ };
+
+ return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0);
+}
+
/*
* wm8400_init - Generic initialisation
*
@@ -296,24 +307,32 @@ static int wm8400_init(struct wm8400 *wm8400,
reg = (reg & WM8400_CHIP_REV_MASK) >> WM8400_CHIP_REV_SHIFT;
dev_info(wm8400->dev, "WM8400 revision %x\n", reg);
+ ret = wm8400_register_codec(wm8400);
+ if (ret != 0) {
+ dev_err(wm8400->dev, "Failed to register codec\n");
+ goto err_children;
+ }
+
if (pdata && pdata->platform_init) {
ret = pdata->platform_init(wm8400->dev);
- if (ret != 0)
+ if (ret != 0) {
dev_err(wm8400->dev, "Platform init failed: %d\n",
ret);
+ goto err_children;
+ }
} else
dev_warn(wm8400->dev, "No platform initialisation supplied\n");
+ return 0;
+
+err_children:
+ mfd_remove_devices(wm8400->dev);
return ret;
}
static void wm8400_release(struct wm8400 *wm8400)
{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(wm8400->regulators); i++)
- if (wm8400->regulators[i].name)
- platform_device_unregister(&wm8400->regulators[i]);
+ mfd_remove_devices(wm8400->dev);
}
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
index 22a7e8ba211..de966a6fb7e 100644
--- a/drivers/misc/ibmasm/ibmasmfs.c
+++ b/drivers/misc/ibmasm/ibmasmfs.c
@@ -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;
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index 517fce48d94..5b396ff6c83 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -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;
}
diff --git a/drivers/net/acenic.h b/drivers/net/acenic.h
index 4487f32759a..c987c9b5a13 100644
--- a/drivers/net/acenic.h
+++ b/drivers/net/acenic.h
@@ -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;
};
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 9f38b16ccbb..134b2d60b47 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -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);
}
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 9930d5f8b9e..6271b9411cc 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -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__ */
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index a2f1905a23d..e3131ea629c 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -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;
diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c
index b0ef46c51a9..cefe1d98f93 100644
--- a/drivers/net/enc28j60.c
+++ b/drivers/net/enc28j60.c
@@ -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) {
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 022794e579c..b82b0fb2056 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -1457,8 +1457,8 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter)
/* Number of supported queues. */
/* Having more queues than CPUs doesn't make sense. */
- adapter->num_rx_queues = min((u32)IGB_MAX_RX_QUEUES, (u32)num_online_cpus());
- adapter->num_tx_queues = min(IGB_MAX_TX_QUEUES, num_online_cpus());
+ adapter->num_rx_queues = min_t(u32, IGB_MAX_RX_QUEUES, num_online_cpus());
+ adapter->num_tx_queues = min_t(u32, IGB_MAX_TX_QUEUES, num_online_cpus());
/* This call may decrease the number of queues depending on
* interrupt mode. */
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 5e70180bf56..6bb71b687f7 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -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:
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h
index ba2e1c5b6bc..459663a4023 100644
--- a/drivers/net/qlge/qlge.h
+++ b/drivers/net/qlge/qlge.h
@@ -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;
diff --git a/drivers/net/qlge/qlge_dbg.c b/drivers/net/qlge/qlge_dbg.c
index 47df304a02c..3f5e02d2e4a 100644
--- a/drivers/net/qlge/qlge_dbg.c
+++ b/drivers/net/qlge/qlge_dbg.c
@@ -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",
diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c
index eefb81b1375..9d922e2ff22 100644
--- a/drivers/net/qlge/qlge_ethtool.c
+++ b/drivers/net/qlge/qlge_ethtool.c
@@ -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);
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index 718a7bd0cd1..f4c016012f1 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -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;
}
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index f54ac2389da..57fb1f71c47 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -42,11 +42,11 @@
#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
index 0a668528955..00000000000
--- a/drivers/net/starfire_firmware.h
+++ /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
index 0c82b80e107..00000000000
--- a/drivers/net/starfire_firmware.pl
+++ /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);
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 04ae1e86aea..5e2dbaee125 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -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>
@@ -137,6 +138,10 @@
#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) {
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 8936edfb043..ae5da603c6a 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -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) */
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 69f9a0ec764..d7b81e4fdd5 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -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;
};
diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c
index ddc4c59f02d..b7e4cee2426 100644
--- a/drivers/oprofile/oprofilefs.c
+++ b/drivers/oprofile/oprofilefs.c
@@ -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;
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 8e0c2b47803..668472405a5 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -29,6 +29,13 @@ config APM_POWER
Say Y here to enable support APM status emulation using
battery class devices.
+config WM8350_POWER
+ tristate "WM8350 PMU support"
+ depends on MFD_WM8350
+ help
+ Say Y here to enable support for the power management unit
+ provided by the Wolfson Microelectronics WM8350 PMIC.
+
config BATTERY_DS2760
tristate "DS2760 battery driver (HP iPAQ & others)"
select W1
@@ -68,4 +75,11 @@ config BATTERY_BQ27x00
help
Say Y here to enable support for batteries with BQ27200(I2C) chip.
+config BATTERY_DA9030
+ tristate "DA9030 battery driver"
+ depends on PMIC_DA903X
+ help
+ Say Y here to enable support for batteries charger integrated into
+ DA9030 PMIC.
+
endif # POWER_SUPPLY
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index e8f1ecec5d8..eebb15505a4 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_POWER_SUPPLY) += power_supply.o
obj-$(CONFIG_PDA_POWER) += pda_power.o
obj-$(CONFIG_APM_POWER) += apm_power.o
+obj-$(CONFIG_WM8350_POWER) += wm8350_power.o
obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o
obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o
@@ -23,3 +24,4 @@ obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o
obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o
obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o
obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o
+obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o
diff --git a/drivers/power/da9030_battery.c b/drivers/power/da9030_battery.c
new file mode 100644
index 00000000000..1662bb0f23a
--- /dev/null
+++ b/drivers/power/da9030_battery.c
@@ -0,0 +1,600 @@
+/*
+ * Battery charger driver for Dialog Semiconductor DA9030
+ *
+ * Copyright (C) 2008 Compulab, Ltd.
+ * Mike Rapoport <mike@compulab.co.il>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/workqueue.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/mfd/da903x.h>
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#define DA9030_STATUS_CHDET (1 << 3)
+
+#define DA9030_FAULT_LOG 0x0a
+#define DA9030_FAULT_LOG_OVER_TEMP (1 << 7)
+#define DA9030_FAULT_LOG_VBAT_OVER (1 << 4)
+
+#define DA9030_CHARGE_CONTROL 0x28
+#define DA9030_CHRG_CHARGER_ENABLE (1 << 7)
+
+#define DA9030_ADC_MAN_CONTROL 0x30
+#define DA9030_ADC_TBATREF_ENABLE (1 << 5)
+#define DA9030_ADC_LDO_INT_ENABLE (1 << 4)
+
+#define DA9030_ADC_AUTO_CONTROL 0x31
+#define DA9030_ADC_TBAT_ENABLE (1 << 5)
+#define DA9030_ADC_VBAT_IN_TXON (1 << 4)
+#define DA9030_ADC_VCH_ENABLE (1 << 3)
+#define DA9030_ADC_ICH_ENABLE (1 << 2)
+#define DA9030_ADC_VBAT_ENABLE (1 << 1)
+#define DA9030_ADC_AUTO_SLEEP_ENABLE (1 << 0)
+
+#define DA9030_VBATMON 0x32
+#define DA9030_VBATMONTXON 0x33
+#define DA9030_TBATHIGHP 0x34
+#define DA9030_TBATHIGHN 0x35
+#define DA9030_TBATLOW 0x36
+
+#define DA9030_VBAT_RES 0x41
+#define DA9030_VBATMIN_RES 0x42
+#define DA9030_VBATMINTXON_RES 0x43
+#define DA9030_ICHMAX_RES 0x44
+#define DA9030_ICHMIN_RES 0x45
+#define DA9030_ICHAVERAGE_RES 0x46
+#define DA9030_VCHMAX_RES 0x47
+#define DA9030_VCHMIN_RES 0x48
+#define DA9030_TBAT_RES 0x49
+
+struct da9030_adc_res {
+ uint8_t vbat_res;
+ uint8_t vbatmin_res;
+ uint8_t vbatmintxon;
+ uint8_t ichmax_res;
+ uint8_t ichmin_res;
+ uint8_t ichaverage_res;
+ uint8_t vchmax_res;
+ uint8_t vchmin_res;
+ uint8_t tbat_res;
+ uint8_t adc_in4_res;
+ uint8_t adc_in5_res;
+};
+
+struct da9030_battery_thresholds {
+ int tbat_low;
+ int tbat_high;
+ int tbat_restart;
+
+ int vbat_low;
+ int vbat_crit;
+ int vbat_charge_start;
+ int vbat_charge_stop;
+ int vbat_charge_restart;
+
+ int vcharge_min;
+ int vcharge_max;
+};
+
+struct da9030_charger {
+ struct power_supply psy;
+
+ struct device *master;
+
+ struct da9030_adc_res adc;
+ struct delayed_work work;
+ unsigned int interval;
+
+ struct power_supply_info *battery_info;
+
+ struct da9030_battery_thresholds thresholds;
+
+ unsigned int charge_milliamp;
+ unsigned int charge_millivolt;
+
+ /* charger status */
+ bool chdet;
+ uint8_t fault;
+ int mA;
+ int mV;
+ bool is_on;
+
+ struct notifier_block nb;
+
+ /* platform callbacks for battery low and critical events */
+ void (*battery_low)(void);
+ void (*battery_critical)(void);
+
+ struct dentry *debug_file;
+};
+
+static inline int da9030_reg_to_mV(int reg)
+{
+ return ((reg * 2650) >> 8) + 2650;
+}
+
+static inline int da9030_millivolt_to_reg(int mV)
+{
+ return ((mV - 2650) << 8) / 2650;
+}
+
+static inline int da9030_reg_to_mA(int reg)
+{
+ return ((reg * 24000) >> 8) / 15;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static int bat_debug_show(struct seq_file *s, void *data)
+{
+ struct da9030_charger *charger = s->private;
+
+ seq_printf(s, "charger is %s\n", charger->is_on ? "on" : "off");
+ if (charger->chdet) {
+ seq_printf(s, "iset = %dmA, vset = %dmV\n",
+ charger->mA, charger->mV);
+ }
+
+ seq_printf(s, "vbat_res = %d (%dmV)\n",
+ charger->adc.vbat_res,
+ da9030_reg_to_mV(charger->adc.vbat_res));
+ seq_printf(s, "vbatmin_res = %d (%dmV)\n",
+ charger->adc.vbatmin_res,
+ da9030_reg_to_mV(charger->adc.vbatmin_res));
+ seq_printf(s, "vbatmintxon = %d (%dmV)\n",
+ charger->adc.vbatmintxon,
+ da9030_reg_to_mV(charger->adc.vbatmintxon));
+ seq_printf(s, "ichmax_res = %d (%dmA)\n",
+ charger->adc.ichmax_res,
+ da9030_reg_to_mV(charger->adc.ichmax_res));
+ seq_printf(s, "ichmin_res = %d (%dmA)\n",
+ charger->adc.ichmin_res,
+ da9030_reg_to_mA(charger->adc.ichmin_res));
+ seq_printf(s, "ichaverage_res = %d (%dmA)\n",
+ charger->adc.ichaverage_res,
+ da9030_reg_to_mA(charger->adc.ichaverage_res));
+ seq_printf(s, "vchmax_res = %d (%dmV)\n",
+ charger->adc.vchmax_res,
+ da9030_reg_to_mA(charger->adc.vchmax_res));
+ seq_printf(s, "vchmin_res = %d (%dmV)\n",
+ charger->adc.vchmin_res,
+ da9030_reg_to_mV(charger->adc.vchmin_res));
+
+ return 0;
+}
+
+static int debug_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, bat_debug_show, inode->i_private);
+}
+
+static const struct file_operations bat_debug_fops = {
+ .open = debug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static struct dentry *da9030_bat_create_debugfs(struct da9030_charger *charger)
+{
+ charger->debug_file = debugfs_create_file("charger", 0666, 0, charger,
+ &bat_debug_fops);
+ return charger->debug_file;
+}
+
+static void da9030_bat_remove_debugfs(struct da9030_charger *charger)
+{
+ debugfs_remove(charger->debug_file);
+}
+#else
+static inline struct dentry *da9030_bat_create_debugfs(struct da9030_charger *charger)
+{
+ return NULL;
+}
+static inline void da9030_bat_remove_debugfs(struct da9030_charger *charger)
+{
+}
+#endif
+
+static inline void da9030_read_adc(struct da9030_charger *charger,
+ struct da9030_adc_res *adc)
+{
+ da903x_reads(charger->master, DA9030_VBAT_RES,
+ sizeof(*adc), (uint8_t *)adc);
+}
+
+static void da9030_charger_update_state(struct da9030_charger *charger)
+{
+ uint8_t val;
+
+ da903x_read(charger->master, DA9030_CHARGE_CONTROL, &val);
+ charger->is_on = (val & DA9030_CHRG_CHARGER_ENABLE) ? 1 : 0;
+ charger->mA = ((val >> 3) & 0xf) * 100;
+ charger->mV = (val & 0x7) * 50 + 4000;
+
+ da9030_read_adc(charger, &charger->adc);
+ da903x_read(charger->master, DA9030_FAULT_LOG, &charger->fault);
+ charger->chdet = da903x_query_status(charger->master,
+ DA9030_STATUS_CHDET);
+}
+
+static void da9030_set_charge(struct da9030_charger *charger, int on)
+{
+ uint8_t val;
+
+ if (on) {
+ val = DA9030_CHRG_CHARGER_ENABLE;
+ val |= (charger->charge_milliamp / 100) << 3;
+ val |= (charger->charge_millivolt - 4000) / 50;
+ charger->is_on = 1;
+ } else {
+ val = 0;
+ charger->is_on = 0;
+ }
+
+ da903x_write(charger->master, DA9030_CHARGE_CONTROL, val);
+}
+
+static void da9030_charger_check_state(struct da9030_charger *charger)
+{
+ da9030_charger_update_state(charger);
+
+ /* we wake or boot with external power on */
+ if (!charger->is_on) {
+ if ((charger->chdet) &&
+ (charger->adc.vbat_res <
+ charger->thresholds.vbat_charge_start)) {
+ da9030_set_charge(charger, 1);
+ }
+ } else {
+ if (charger->adc.vbat_res >=
+ charger->thresholds.vbat_charge_stop) {
+ da9030_set_charge(charger, 0);
+ da903x_write(charger->master, DA9030_VBATMON,
+ charger->thresholds.vbat_charge_restart);
+ } else if (charger->adc.vbat_res >
+ charger->thresholds.vbat_low) {
+ /* we are charging and passed LOW_THRESH,
+ so upate DA9030 VBAT threshold
+ */
+ da903x_write(charger->master, DA9030_VBATMON,
+ charger->thresholds.vbat_low);
+ }
+ if (charger->adc.vchmax_res > charger->thresholds.vcharge_max ||
+ charger->adc.vchmin_res < charger->thresholds.vcharge_min ||
+ /* Tempreture readings are negative */
+ charger->adc.tbat_res < charger->thresholds.tbat_high ||
+ charger->adc.tbat_res > charger->thresholds.tbat_low) {
+ /* disable charger */
+ da9030_set_charge(charger, 0);
+ }
+ }
+}
+
+static void da9030_charging_monitor(struct work_struct *work)
+{
+ struct da9030_charger *charger;
+
+ charger = container_of(work, struct da9030_charger, work.work);
+
+ da9030_charger_check_state(charger);
+
+ /* reschedule for the next time */
+ schedule_delayed_work(&charger->work, charger->interval);
+}
+
+static enum power_supply_property da9030_battery_props[] = {
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_AVG,
+};
+
+static void da9030_battery_check_status(struct da9030_charger *charger,
+ union power_supply_propval *val)
+{
+ if (charger->chdet) {
+ if (charger->is_on)
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ } else {
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ }
+}
+
+static void da9030_battery_check_health(struct da9030_charger *charger,
+ union power_supply_propval *val)
+{
+ if (charger->fault & DA9030_FAULT_LOG_OVER_TEMP)
+ val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
+ else if (charger->fault & DA9030_FAULT_LOG_VBAT_OVER)
+ val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+ else
+ val->intval = POWER_SUPPLY_HEALTH_GOOD;
+}
+
+static int da9030_battery_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct da9030_charger *charger;
+ charger = container_of(psy, struct da9030_charger, psy);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ da9030_battery_check_status(charger, val);
+ break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ da9030_battery_check_health(charger, val);
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ val->intval = charger->battery_info->technology;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+ val->intval = charger->battery_info->voltage_max_design;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+ val->intval = charger->battery_info->voltage_min_design;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = da9030_reg_to_mV(charger->adc.vbat_res) * 1000;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_AVG:
+ val->intval =
+ da9030_reg_to_mA(charger->adc.ichaverage_res) * 1000;
+ break;
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ val->strval = charger->battery_info->name;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static void da9030_battery_vbat_event(struct da9030_charger *charger)
+{
+ da9030_read_adc(charger, &charger->adc);
+
+ if (charger->is_on)
+ return;
+
+ if (charger->adc.vbat_res < charger->thresholds.vbat_low) {
+ /* set VBAT threshold for critical */
+ da903x_write(charger->master, DA9030_VBATMON,
+ charger->thresholds.vbat_crit);
+ if (charger->battery_low)
+ charger->battery_low();
+ } else if (charger->adc.vbat_res <
+ charger->thresholds.vbat_crit) {
+ /* notify the system of battery critical */
+ if (charger->battery_critical)
+ charger->battery_critical();
+ }
+}
+
+static int da9030_battery_event(struct notifier_block *nb, unsigned long event,
+ void *data)
+{
+ struct da9030_charger *charger =
+ container_of(nb, struct da9030_charger, nb);
+ int status;
+
+ switch (event) {
+ case DA9030_EVENT_CHDET:
+ status = da903x_query_status(charger->master,
+ DA9030_STATUS_CHDET);
+ da9030_set_charge(charger, status);
+ break;
+ case DA9030_EVENT_VBATMON:
+ da9030_battery_vbat_event(charger);
+ break;
+ case DA9030_EVENT_CHIOVER:
+ case DA9030_EVENT_TBAT:
+ da9030_set_charge(charger, 0);
+ break;
+ }
+
+ return 0;
+}
+
+static void da9030_battery_convert_thresholds(struct da9030_charger *charger,
+ struct da9030_battery_info *pdata)
+{
+ charger->thresholds.tbat_low = pdata->tbat_low;
+ charger->thresholds.tbat_high = pdata->tbat_high;
+ charger->thresholds.tbat_restart = pdata->tbat_restart;
+
+ charger->thresholds.vbat_low =
+ da9030_millivolt_to_reg(pdata->vbat_low);
+ charger->thresholds.vbat_crit =
+ da9030_millivolt_to_reg(pdata->vbat_crit);
+ charger->thresholds.vbat_charge_start =
+ da9030_millivolt_to_reg(pdata->vbat_charge_start);
+ charger->thresholds.vbat_charge_stop =
+ da9030_millivolt_to_reg(pdata->vbat_charge_stop);
+ charger->thresholds.vbat_charge_restart =
+ da9030_millivolt_to_reg(pdata->vbat_charge_restart);
+
+ charger->thresholds.vcharge_min =
+ da9030_millivolt_to_reg(pdata->vcharge_min);
+ charger->thresholds.vcharge_max =
+ da9030_millivolt_to_reg(pdata->vcharge_max);
+}
+
+static void da9030_battery_setup_psy(struct da9030_charger *charger)
+{
+ struct power_supply *psy = &charger->psy;
+ struct power_supply_info *info = charger->battery_info;
+
+ psy->name = info->name;
+ psy->use_for_apm = info->use_for_apm;
+ psy->type = POWER_SUPPLY_TYPE_BATTERY;
+ psy->get_property = da9030_battery_get_property;
+
+ psy->properties = da9030_battery_props;
+ psy->num_properties = ARRAY_SIZE(da9030_battery_props);
+};
+
+static int da9030_battery_charger_init(struct da9030_charger *charger)
+{
+ char v[5];
+ int ret;
+
+ v[0] = v[1] = charger->thresholds.vbat_low;
+ v[2] = charger->thresholds.tbat_high;
+ v[3] = charger->thresholds.tbat_restart;
+ v[4] = charger->thresholds.tbat_low;
+
+ ret = da903x_writes(charger->master, DA9030_VBATMON, 5, v);
+ if (ret)
+ return ret;
+
+ /*
+ * Enable reference voltage supply for ADC from the LDO_INTERNAL
+ * regulator. Must be set before ADC measurements can be made.
+ */
+ ret = da903x_write(charger->master, DA9030_ADC_MAN_CONTROL,
+ DA9030_ADC_LDO_INT_ENABLE |
+ DA9030_ADC_TBATREF_ENABLE);
+ if (ret)
+ return ret;
+
+ /* enable auto ADC measuremnts */
+ return da903x_write(charger->master, DA9030_ADC_AUTO_CONTROL,
+ DA9030_ADC_TBAT_ENABLE | DA9030_ADC_VBAT_IN_TXON |
+ DA9030_ADC_VCH_ENABLE | DA9030_ADC_ICH_ENABLE |
+ DA9030_ADC_VBAT_ENABLE |
+ DA9030_ADC_AUTO_SLEEP_ENABLE);
+}
+
+static int da9030_battery_probe(struct platform_device *pdev)
+{
+ struct da9030_charger *charger;
+ struct da9030_battery_info *pdata = pdev->dev.platform_data;
+ int ret;
+
+ if (pdata == NULL)
+ return -EINVAL;
+
+ if (pdata->charge_milliamp >= 1500 ||
+ pdata->charge_millivolt < 4000 ||
+ pdata->charge_millivolt > 4350)
+ return -EINVAL;
+
+ charger = kzalloc(sizeof(*charger), GFP_KERNEL);
+ if (charger == NULL)
+ return -ENOMEM;
+
+ charger->master = pdev->dev.parent;
+
+ /* 10 seconds between monotor runs unless platfrom defines other
+ interval */
+ charger->interval = msecs_to_jiffies(
+ (pdata->batmon_interval ? : 10) * 1000);
+
+ charger->charge_milliamp = pdata->charge_milliamp;
+ charger->charge_millivolt = pdata->charge_millivolt;
+ charger->battery_info = pdata->battery_info;
+ charger->battery_low = pdata->battery_low;
+ charger->battery_critical = pdata->battery_critical;
+
+ da9030_battery_convert_thresholds(charger, pdata);
+
+ ret = da9030_battery_charger_init(charger);
+ if (ret)
+ goto err_charger_init;
+
+ INIT_DELAYED_WORK(&charger->work, da9030_charging_monitor);
+ schedule_delayed_work(&charger->work, charger->interval);
+
+ charger->nb.notifier_call = da9030_battery_event;
+ ret = da903x_register_notifier(charger->master, &charger->nb,
+ DA9030_EVENT_CHDET |
+ DA9030_EVENT_VBATMON |
+ DA9030_EVENT_CHIOVER |
+ DA9030_EVENT_TBAT);
+ if (ret)
+ goto err_notifier;
+
+ da9030_battery_setup_psy(charger);
+ ret = power_supply_register(&pdev->dev, &charger->psy);
+ if (ret)
+ goto err_ps_register;
+
+ charger->debug_file = da9030_bat_create_debugfs(charger);
+ platform_set_drvdata(pdev, charger);
+ return 0;
+
+err_ps_register:
+ da903x_unregister_notifier(charger->master, &charger->nb,
+ DA9030_EVENT_CHDET | DA9030_EVENT_VBATMON |
+ DA9030_EVENT_CHIOVER | DA9030_EVENT_TBAT);
+err_notifier:
+ cancel_delayed_work(&charger->work);
+
+err_charger_init:
+ kfree(charger);
+
+ return ret;
+}
+
+static int da9030_battery_remove(struct platform_device *dev)
+{
+ struct da9030_charger *charger = platform_get_drvdata(dev);
+
+ da9030_bat_remove_debugfs(charger);
+
+ da903x_unregister_notifier(charger->master, &charger->nb,
+ DA9030_EVENT_CHDET | DA9030_EVENT_VBATMON |
+ DA9030_EVENT_CHIOVER | DA9030_EVENT_TBAT);
+ cancel_delayed_work(&charger->work);
+ power_supply_unregister(&charger->psy);
+
+ kfree(charger);
+
+ return 0;
+}
+
+static struct platform_driver da903x_battery_driver = {
+ .driver = {
+ .name = "da903x-battery",
+ .owner = THIS_MODULE,
+ },
+ .probe = da9030_battery_probe,
+ .remove = da9030_battery_remove,
+};
+
+static int da903x_battery_init(void)
+{
+ return platform_driver_register(&da903x_battery_driver);
+}
+
+static void da903x_battery_exit(void)
+{
+ platform_driver_unregister(&da903x_battery_driver);
+}
+
+module_init(da903x_battery_init);
+module_exit(da903x_battery_exit);
+
+MODULE_DESCRIPTION("DA9030 battery charger driver");
+MODULE_AUTHOR("Mike Rapoport, CompuLab");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index 23ae8460f5c..ac01e06817f 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -45,7 +45,7 @@ static ssize_t power_supply_show_property(struct device *dev,
};
static char *health_text[] = {
"Unknown", "Good", "Overheat", "Dead", "Over voltage",
- "Unspecified failure"
+ "Unspecified failure", "Cold",
};
static char *technology_text[] = {
"Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd",
diff --git a/drivers/power/wm8350_power.c b/drivers/power/wm8350_power.c
new file mode 100644
index 00000000000..1b16bf343f2
--- /dev/null
+++ b/drivers/power/wm8350_power.c
@@ -0,0 +1,532 @@
+/*
+ * Battery driver for wm8350 PMIC
+ *
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ *
+ * Based on OLPC Battery Driver
+ *
+ * Copyright 2006 David Woodhouse <dwmw2@infradead.org>
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/mfd/wm8350/supply.h>
+#include <linux/mfd/wm8350/core.h>
+#include <linux/mfd/wm8350/comparator.h>
+
+static int wm8350_read_battery_uvolts(struct wm8350 *wm8350)
+{
+ return wm8350_read_auxadc(wm8350, WM8350_AUXADC_BATT, 0, 0)
+ * WM8350_AUX_COEFF;
+}
+
+static int wm8350_read_line_uvolts(struct wm8350 *wm8350)
+{
+ return wm8350_read_auxadc(wm8350, WM8350_AUXADC_LINE, 0, 0)
+ * WM8350_AUX_COEFF;
+}
+
+static int wm8350_read_usb_uvolts(struct wm8350 *wm8350)
+{
+ return wm8350_read_auxadc(wm8350, WM8350_AUXADC_USB, 0, 0)
+ * WM8350_AUX_COEFF;
+}
+
+#define WM8350_BATT_SUPPLY 1
+#define WM8350_USB_SUPPLY 2
+#define WM8350_LINE_SUPPLY 4
+
+static inline int wm8350_charge_time_min(struct wm8350 *wm8350, int min)
+{
+ if (!wm8350->power.rev_g_coeff)
+ return (((min - 30) / 15) & 0xf) << 8;
+ else
+ return (((min - 30) / 30) & 0xf) << 8;
+}
+
+static int wm8350_get_supplies(struct wm8350 *wm8350)
+{
+ u16 sm, ov, co, chrg;
+ int supplies = 0;
+
+ sm = wm8350_reg_read(wm8350, WM8350_STATE_MACHINE_STATUS);
+ ov = wm8350_reg_read(wm8350, WM8350_MISC_OVERRIDES);
+ co = wm8350_reg_read(wm8350, WM8350_COMPARATOR_OVERRIDES);
+ chrg = wm8350_reg_read(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2);
+
+ /* USB_SM */
+ sm = (sm & WM8350_USB_SM_MASK) >> WM8350_USB_SM_SHIFT;
+
+ /* CHG_ISEL */
+ chrg &= WM8350_CHG_ISEL_MASK;
+
+ /* If the USB state machine is active then we're using that with or
+ * without battery, otherwise check for wall supply */
+ if (((sm == WM8350_USB_SM_100_SLV) ||
+ (sm == WM8350_USB_SM_500_SLV) ||
+ (sm == WM8350_USB_SM_STDBY_SLV))
+ && !(ov & WM8350_USB_LIMIT_OVRDE))
+ supplies = WM8350_USB_SUPPLY;
+ else if (((sm == WM8350_USB_SM_100_SLV) ||
+ (sm == WM8350_USB_SM_500_SLV) ||
+ (sm == WM8350_USB_SM_STDBY_SLV))
+ && (ov & WM8350_USB_LIMIT_OVRDE) && (chrg == 0))
+ supplies = WM8350_USB_SUPPLY | WM8350_BATT_SUPPLY;
+ else if (co & WM8350_WALL_FB_OVRDE)
+ supplies = WM8350_LINE_SUPPLY;
+ else
+ supplies = WM8350_BATT_SUPPLY;
+
+ return supplies;
+}
+
+static int wm8350_charger_config(struct wm8350 *wm8350,
+ struct wm8350_charger_policy *policy)
+{
+ u16 reg, eoc_mA, fast_limit_mA;
+
+ if (!policy) {
+ dev_warn(wm8350->dev,
+ "No charger policy, charger not configured.\n");
+ return -EINVAL;
+ }
+
+ /* make sure USB fast charge current is not > 500mA */
+ if (policy->fast_limit_USB_mA > 500) {
+ dev_err(wm8350->dev, "USB fast charge > 500mA\n");
+ return -EINVAL;
+ }
+
+ eoc_mA = WM8350_CHG_EOC_mA(policy->eoc_mA);
+
+ wm8350_reg_unlock(wm8350);
+
+ reg = wm8350_reg_read(wm8350, WM8350_BATTERY_CHARGER_CONTROL_1)
+ & WM8350_CHG_ENA_R168;
+ wm8350_reg_write(wm8350, WM8350_BATTERY_CHARGER_CONTROL_1,
+ reg | eoc_mA | policy->trickle_start_mV |
+ WM8350_CHG_TRICKLE_TEMP_CHOKE |
+ WM8350_CHG_TRICKLE_USB_CHOKE |
+ WM8350_CHG_FAST_USB_THROTTLE);
+
+ if (wm8350_get_supplies(wm8350) & WM8350_USB_SUPPLY) {
+ fast_limit_mA =
+ WM8350_CHG_FAST_LIMIT_mA(policy->fast_limit_USB_mA);
+ wm8350_reg_write(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2,
+ policy->charge_mV | policy->trickle_charge_USB_mA |
+ fast_limit_mA | wm8350_charge_time_min(wm8350,
+ policy->charge_timeout));
+
+ } else {
+ fast_limit_mA =
+ WM8350_CHG_FAST_LIMIT_mA(policy->fast_limit_mA);
+ wm8350_reg_write(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2,
+ policy->charge_mV | policy->trickle_charge_mA |
+ fast_limit_mA | wm8350_charge_time_min(wm8350,
+ policy->charge_timeout));
+ }
+
+ wm8350_reg_lock(wm8350);
+ return 0;
+}
+
+static int wm8350_batt_status(struct wm8350 *wm8350)
+{
+ u16 state;
+
+ state = wm8350_reg_read(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2);
+ state &= WM8350_CHG_STS_MASK;
+
+ switch (state) {
+ case WM8350_CHG_STS_OFF:
+ return POWER_SUPPLY_STATUS_DISCHARGING;
+
+ case WM8350_CHG_STS_TRICKLE:
+ case WM8350_CHG_STS_FAST:
+ return POWER_SUPPLY_STATUS_CHARGING;
+
+ default:
+ return POWER_SUPPLY_STATUS_UNKNOWN;
+ }
+}
+
+static ssize_t charger_state_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct wm8350 *wm8350 = dev_get_drvdata(dev);
+ char *charge;
+ int state;
+
+ state = wm8350_reg_read(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2) &
+ WM8350_CHG_STS_MASK;
+ switch (state) {
+ case WM8350_CHG_STS_OFF:
+ charge = "Charger Off";
+ break;
+ case WM8350_CHG_STS_TRICKLE:
+ charge = "Trickle Charging";
+ break;
+ case WM8350_CHG_STS_FAST:
+ charge = "Fast Charging";
+ break;
+ default:
+ return 0;
+ }
+
+ return sprintf(buf, "%s\n", charge);
+}
+
+static DEVICE_ATTR(charger_state, 0444, charger_state_show, NULL);
+
+static void wm8350_charger_handler(struct wm8350 *wm8350, int irq, void *data)
+{
+ struct wm8350_power *power = &wm8350->power;
+ struct wm8350_charger_policy *policy = power->policy;
+
+ switch (irq) {
+ case WM8350_IRQ_CHG_BAT_FAIL:
+ dev_err(wm8350->dev, "battery failed\n");
+ break;
+ case WM8350_IRQ_CHG_TO:
+ dev_err(wm8350->dev, "charger timeout\n");
+ power_supply_changed(&power->battery);
+ break;
+
+ case WM8350_IRQ_CHG_BAT_HOT:
+ case WM8350_IRQ_CHG_BAT_COLD:
+ case WM8350_IRQ_CHG_START:
+ case WM8350_IRQ_CHG_END:
+ power_supply_changed(&power->battery);
+ break;
+
+ case WM8350_IRQ_CHG_FAST_RDY:
+ dev_dbg(wm8350->dev, "fast charger ready\n");
+ wm8350_charger_config(wm8350, policy);
+ wm8350_reg_unlock(wm8350);
+ wm8350_set_bits(wm8350, WM8350_BATTERY_CHARGER_CONTROL_1,
+ WM8350_CHG_FAST);
+ wm8350_reg_lock(wm8350);
+ break;
+
+ case WM8350_IRQ_CHG_VBATT_LT_3P9:
+ dev_warn(wm8350->dev, "battery < 3.9V\n");
+ break;
+ case WM8350_IRQ_CHG_VBATT_LT_3P1:
+ dev_warn(wm8350->dev, "battery < 3.1V\n");
+ break;
+ case WM8350_IRQ_CHG_VBATT_LT_2P85:
+ dev_warn(wm8350->dev, "battery < 2.85V\n");
+ break;
+
+ /* Supply change. We will overnotify but it should do
+ * no harm. */
+ case WM8350_IRQ_EXT_USB_FB:
+ case WM8350_IRQ_EXT_WALL_FB:
+ wm8350_charger_config(wm8350, policy);
+ case WM8350_IRQ_EXT_BAT_FB: /* Fall through */
+ power_supply_changed(&power->battery);
+ power_supply_changed(&power->usb);
+ power_supply_changed(&power->ac);
+ break;
+
+ default:
+ dev_err(wm8350->dev, "Unknown interrupt %d\n", irq);
+ }
+}
+
+/*********************************************************************
+ * AC Power
+ *********************************************************************/
+static int wm8350_ac_get_prop(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct wm8350 *wm8350 = dev_get_drvdata(psy->dev->parent);
+ int ret = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = !!(wm8350_get_supplies(wm8350) &
+ WM8350_LINE_SUPPLY);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = wm8350_read_line_uvolts(wm8350);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static enum power_supply_property wm8350_ac_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+};
+
+/*********************************************************************
+ * USB Power
+ *********************************************************************/
+static int wm8350_usb_get_prop(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct wm8350 *wm8350 = dev_get_drvdata(psy->dev->parent);
+ int ret = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = !!(wm8350_get_supplies(wm8350) &
+ WM8350_USB_SUPPLY);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = wm8350_read_usb_uvolts(wm8350);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static enum power_supply_property wm8350_usb_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+};
+
+/*********************************************************************
+ * Battery properties
+ *********************************************************************/
+
+static int wm8350_bat_check_health(struct wm8350 *wm8350)
+{
+ u16 reg;
+
+ if (wm8350_read_battery_uvolts(wm8350) < 2850000)
+ return POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+
+ reg = wm8350_reg_read(wm8350, WM8350_CHARGER_OVERRIDES);
+ if (reg & WM8350_CHG_BATT_HOT_OVRDE)
+ return POWER_SUPPLY_HEALTH_OVERHEAT;
+
+ if (reg & WM8350_CHG_BATT_COLD_OVRDE)
+ return POWER_SUPPLY_HEALTH_COLD;
+
+ return POWER_SUPPLY_HEALTH_GOOD;
+}
+
+static int wm8350_bat_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct wm8350 *wm8350 = dev_get_drvdata(psy->dev->parent);
+ int ret = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = wm8350_batt_status(wm8350);
+ break;
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = !!(wm8350_get_supplies(wm8350) &
+ WM8350_BATT_SUPPLY);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = wm8350_read_battery_uvolts(wm8350);
+ break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ val->intval = wm8350_bat_check_health(wm8350);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static enum power_supply_property wm8350_bat_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_HEALTH,
+};
+
+/*********************************************************************
+ * Initialisation
+ *********************************************************************/
+
+static void wm8350_init_charger(struct wm8350 *wm8350)
+{
+ /* register our interest in charger events */
+ wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT);
+ wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD);
+ wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL);
+ wm8350_register_irq(wm8350, WM8350_IRQ_CHG_TO,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_TO);
+ wm8350_register_irq(wm8350, WM8350_IRQ_CHG_END,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_END);
+ wm8350_register_irq(wm8350, WM8350_IRQ_CHG_START,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_START);
+ wm8350_register_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY);
+ wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9);
+ wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1);
+ wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85);
+
+ /* and supply change events */
+ wm8350_register_irq(wm8350, WM8350_IRQ_EXT_USB_FB,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_USB_FB);
+ wm8350_register_irq(wm8350, WM8350_IRQ_EXT_WALL_FB,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_WALL_FB);
+ wm8350_register_irq(wm8350, WM8350_IRQ_EXT_BAT_FB,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_BAT_FB);
+}
+
+static void free_charger_irq(struct wm8350 *wm8350)
+{
+ wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_TO);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_END);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_START);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_USB_FB);
+ wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_WALL_FB);
+ wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_BAT_FB);
+ wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB);
+}
+
+static __devinit int wm8350_power_probe(struct platform_device *pdev)
+{
+ struct wm8350 *wm8350 = platform_get_drvdata(pdev);
+ struct wm8350_power *power = &wm8350->power;
+ struct wm8350_charger_policy *policy = power->policy;
+ struct power_supply *usb = &power->usb;
+ struct power_supply *battery = &power->battery;
+ struct power_supply *ac = &power->ac;
+ int ret;
+
+ ac->name = "wm8350-ac";
+ ac->type = POWER_SUPPLY_TYPE_MAINS;
+ ac->properties = wm8350_ac_props;
+ ac->num_properties = ARRAY_SIZE(wm8350_ac_props);
+ ac->get_property = wm8350_ac_get_prop;
+ ret = power_supply_register(&pdev->dev, ac);
+ if (ret)
+ return ret;
+
+ battery->name = "wm8350-battery";
+ battery->properties = wm8350_bat_props;
+ battery->num_properties = ARRAY_SIZE(wm8350_bat_props);
+ battery->get_property = wm8350_bat_get_property;
+ battery->use_for_apm = 1;
+ ret = power_supply_register(&pdev->dev, battery);
+ if (ret)
+ goto battery_failed;
+
+ usb->name = "wm8350-usb",
+ usb->type = POWER_SUPPLY_TYPE_USB;
+ usb->properties = wm8350_usb_props;
+ usb->num_properties = ARRAY_SIZE(wm8350_usb_props);
+ usb->get_property = wm8350_usb_get_prop;
+ ret = power_supply_register(&pdev->dev, usb);
+ if (ret)
+ goto usb_failed;
+
+ ret = device_create_file(&pdev->dev, &dev_attr_charger_state);
+ if (ret < 0)
+ dev_warn(wm8350->dev, "failed to add charge sysfs: %d\n", ret);
+ ret = 0;
+
+ wm8350_init_charger(wm8350);
+ if (wm8350_charger_config(wm8350, policy) == 0) {
+ wm8350_reg_unlock(wm8350);
+ wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CHG_ENA);
+ wm8350_reg_lock(wm8350);
+ }
+
+ return ret;
+
+usb_failed:
+ power_supply_unregister(battery);
+battery_failed:
+ power_supply_unregister(ac);
+
+ return ret;
+}
+
+static __devexit int wm8350_power_remove(struct platform_device *pdev)
+{
+ struct wm8350 *wm8350 = platform_get_drvdata(pdev);
+ struct wm8350_power *power = &wm8350->power;
+
+ free_charger_irq(wm8350);
+ device_remove_file(&pdev->dev, &dev_attr_charger_state);
+ power_supply_unregister(&power->battery);
+ power_supply_unregister(&power->ac);
+ power_supply_unregister(&power->usb);
+ return 0;
+}
+
+static struct platform_driver wm8350_power_driver = {
+ .probe = wm8350_power_probe,
+ .remove = __devexit_p(wm8350_power_remove),
+ .driver = {
+ .name = "wm8350-power",
+ },
+};
+
+static int __init wm8350_power_init(void)
+{
+ return platform_driver_register(&wm8350_power_driver);
+}
+module_init(wm8350_power_init);
+
+static void __exit wm8350_power_exit(void)
+{
+ platform_driver_unregister(&wm8350_power_driver);
+}
+module_exit(wm8350_power_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Power supply driver for WM8350");
+MODULE_ALIAS("platform:wm8350-power");
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c
index 1f44b17e23b..c68c496b2c4 100644
--- a/drivers/regulator/wm8350-regulator.c
+++ b/drivers/regulator/wm8350-regulator.c
@@ -1380,6 +1380,13 @@ int wm8350_register_regulator(struct wm8350 *wm8350, int reg,
if (wm8350->pmic.pdev[reg])
return -EBUSY;
+ if (reg >= WM8350_DCDC_1 && reg <= WM8350_DCDC_6 &&
+ reg > wm8350->pmic.max_dcdc)
+ return -ENODEV;
+ if (reg >= WM8350_ISINK_A && reg <= WM8350_ISINK_B &&
+ reg > wm8350->pmic.max_isink)
+ return -ENODEV;
+
pdev = platform_device_alloc("wm8350-regulator", reg);
if (!pdev)
return -ENOMEM;
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 123092d8a98..165a8184335 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -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
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index a04c1b6b157..fd2c652504f 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -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
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index ecdea44ae4e..45152f4952d 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -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)
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index d5ccce1643e..e0c45574b0c 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -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;
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index e783644a210..6811dd529f4 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -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)
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 2c48591ced4..21627ba3093 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -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");
}
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index c0b30b25a5f..cfda1ecffdf 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -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);
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index 185be760833..2a129cb7bb5 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -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:
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index c4e62a6297d..2e71368f45b 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -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)
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index eeb26c0f88e..317b48fdbf0 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -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;
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 73ac754ad80..e21fe5b6f9f 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -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)
diff --git a/firmware/Makefile b/firmware/Makefile
index 6968388818b..d872b7942a3 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -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
diff --git a/firmware/WHENCE b/firmware/WHENCE
index 8f06639ba3e..1bb2cf4b173 100644
--- a/firmware/WHENCE
+++ b/firmware/WHENCE
@@ -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
index 00000000000..bef2659d364
--- /dev/null
+++ b/firmware/acenic/tg1.bin.ihex
@@ -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
index 00000000000..a9ff4f431f2
--- /dev/null
+++ b/firmware/acenic/tg2.bin.ihex
@@ -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
index 00000000000..6b1fae0d18e
--- /dev/null
+++ b/firmware/adaptec/starfire_rx.bin.ihex
@@ -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
index 00000000000..6b1fae0d18e
--- /dev/null
+++ b/firmware/adaptec/starfire_tx.bin.ihex
@@ -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
index 00000000000..d842d7cc91b
--- /dev/null
+++ b/firmware/tigon/tg3.bin.ihex
@@ -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
index 00000000000..f10c4ef9051
--- /dev/null
+++ b/firmware/tigon/tg3_tso.bin.ihex
@@ -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
index 00000000000..33672514eab
--- /dev/null
+++ b/firmware/tigon/tg3_tso5.bin.ihex
@@ -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. */
diff --git a/fs/Kconfig b/fs/Kconfig
index ff0e8198020..f9b6e2979aa 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -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.
diff --git a/fs/Makefile b/fs/Makefile
index e6f423d1d22..c830611550d 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -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/
diff --git a/fs/affs/file.c b/fs/affs/file.c
index 1377b1240b6..9246cb4aa01 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -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;
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index 415d9c67ac1..3c4ec7d864c 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -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:
diff --git a/fs/afs/write.c b/fs/afs/write.c
index d6b85dab35f..3fb36d43362 100644
--- a/fs/afs/write.c
+++ b/fs/afs/write.c
@@ -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;
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
index c773680d5c6..e1734f2d6e2 100644
--- a/fs/autofs/inode.c
+++ b/fs/autofs/inode.c
@@ -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;
}
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 7b19802cfef..cfc23e53b6f 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -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)) {
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index f2744ab4e5b..e1158cb4fbd 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -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);
}
diff --git a/fs/buffer.c b/fs/buffer.c
index 776ae091d3b..a13f09b696f 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -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;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index b1e1fc6a6e6..12bb656fbe7 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -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;
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index f247da9f4ed..5ab9896fdcb 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -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:
diff --git a/fs/coda/file.c b/fs/coda/file.c
index 466303db2df..6a347fbc998 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -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));
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
index 4803ccc9448..5d349d38e05 100644
--- a/fs/configfs/inode.c
+++ b/fs/configfs/inode.c
@@ -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;
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index f40423eb1a1..a07338d2d14 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -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));
}
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 3dbe2169cf3..81ae9ea3c6e 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -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:
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index fff96e152c0..5f3231b9633 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -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;
diff --git a/fs/dlm/ast.c b/fs/dlm/ast.c
index 8bf31e3fbf0..dc2ad6008b2 100644
--- a/fs/dlm/ast.c
+++ b/fs/dlm/ast.c
@@ -2,7 +2,7 @@
*******************************************************************************
**
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+** Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
@@ -33,10 +33,10 @@ void dlm_del_ast(struct dlm_lkb *lkb)
spin_unlock(&ast_queue_lock);
}
-void dlm_add_ast(struct dlm_lkb *lkb, int type)
+void dlm_add_ast(struct dlm_lkb *lkb, int type, int bastmode)
{
if (lkb->lkb_flags & DLM_IFL_USER) {
- dlm_user_add_ast(lkb, type);
+ dlm_user_add_ast(lkb, type, bastmode);
return;
}
@@ -46,6 +46,8 @@ void dlm_add_ast(struct dlm_lkb *lkb, int type)
list_add_tail(&lkb->lkb_astqueue, &ast_queue);
}
lkb->lkb_ast_type |= type;
+ if (bastmode)
+ lkb->lkb_bastmode = bastmode;
spin_unlock(&ast_queue_lock);
set_bit(WAKE_ASTS, &astd_wakeflags);
@@ -59,50 +61,40 @@ static void process_asts(void)
struct dlm_lkb *lkb;
void (*cast) (void *astparam);
void (*bast) (void *astparam, int mode);
- int type = 0, found, bmode;
-
- for (;;) {
- found = 0;
- spin_lock(&ast_queue_lock);
- list_for_each_entry(lkb, &ast_queue, lkb_astqueue) {
- r = lkb->lkb_resource;
- ls = r->res_ls;
-
- if (dlm_locking_stopped(ls))
- continue;
-
- list_del(&lkb->lkb_astqueue);
- type = lkb->lkb_ast_type;
- lkb->lkb_ast_type = 0;
- found = 1;
- break;
- }
- spin_unlock(&ast_queue_lock);
+ int type = 0, bastmode;
+
+repeat:
+ spin_lock(&ast_queue_lock);
+ list_for_each_entry(lkb, &ast_queue, lkb_astqueue) {
+ r = lkb->lkb_resource;
+ ls = r->res_ls;
+
+ if (dlm_locking_stopped(ls))
+ continue;
- if (!found)
- break;
+ list_del(&lkb->lkb_astqueue);
+ type = lkb->lkb_ast_type;
+ lkb->lkb_ast_type = 0;
+ bastmode = lkb->lkb_bastmode;
+ spin_unlock(&ast_queue_lock);
cast = lkb->lkb_astfn;
bast = lkb->lkb_bastfn;
- bmode = lkb->lkb_bastmode;
if ((type & AST_COMP) && cast)
cast(lkb->lkb_astparam);
- /* FIXME: Is it safe to look at lkb_grmode here
- without doing a lock_rsb() ?
- Look at other checks in v1 to avoid basts. */
-
if ((type & AST_BAST) && bast)
- if (!dlm_modes_compat(lkb->lkb_grmode, bmode))
- bast(lkb->lkb_astparam, bmode);
+ bast(lkb->lkb_astparam, bastmode);
/* this removes the reference added by dlm_add_ast
and may result in the lkb being freed */
dlm_put_lkb(lkb);
- schedule();
+ cond_resched();
+ goto repeat;
}
+ spin_unlock(&ast_queue_lock);
}
static inline int no_asts(void)
diff --git a/fs/dlm/ast.h b/fs/dlm/ast.h
index 6ee276c74c5..1b5fc5f428f 100644
--- a/fs/dlm/ast.h
+++ b/fs/dlm/ast.h
@@ -1,7 +1,7 @@
/******************************************************************************
*******************************************************************************
**
-** Copyright (C) 2005 Red Hat, Inc. All rights reserved.
+** Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
@@ -13,7 +13,7 @@
#ifndef __ASTD_DOT_H__
#define __ASTD_DOT_H__
-void dlm_add_ast(struct dlm_lkb *lkb, int type);
+void dlm_add_ast(struct dlm_lkb *lkb, int type, int bastmode);
void dlm_del_ast(struct dlm_lkb *lkb);
void dlm_astd_wake(void);
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c
index 8fc24f4507a..2f107d1a6a4 100644
--- a/fs/dlm/debug_fs.c
+++ b/fs/dlm/debug_fs.c
@@ -1,7 +1,7 @@
/******************************************************************************
*******************************************************************************
**
-** Copyright (C) 2005 Red Hat, Inc. All rights reserved.
+** Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
@@ -27,7 +27,7 @@ static struct dentry *dlm_root;
struct rsb_iter {
int entry;
- int locks;
+ int format;
int header;
struct dlm_ls *ls;
struct list_head *next;
@@ -60,8 +60,8 @@ static char *print_lockmode(int mode)
}
}
-static void print_resource_lock(struct seq_file *s, struct dlm_lkb *lkb,
- struct dlm_rsb *res)
+static void print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
+ struct dlm_rsb *res)
{
seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode));
@@ -83,7 +83,7 @@ static void print_resource_lock(struct seq_file *s, struct dlm_lkb *lkb,
seq_printf(s, "\n");
}
-static int print_resource(struct dlm_rsb *res, struct seq_file *s)
+static int print_format1(struct dlm_rsb *res, struct seq_file *s)
{
struct dlm_lkb *lkb;
int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list;
@@ -134,15 +134,15 @@ static int print_resource(struct dlm_rsb *res, struct seq_file *s)
/* Print the locks attached to this resource */
seq_printf(s, "Granted Queue\n");
list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue)
- print_resource_lock(s, lkb, res);
+ print_format1_lock(s, lkb, res);
seq_printf(s, "Conversion Queue\n");
list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue)
- print_resource_lock(s, lkb, res);
+ print_format1_lock(s, lkb, res);
seq_printf(s, "Waiting Queue\n");
list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue)
- print_resource_lock(s, lkb, res);
+ print_format1_lock(s, lkb, res);
if (list_empty(&res->res_lookup))
goto out;
@@ -160,23 +160,24 @@ static int print_resource(struct dlm_rsb *res, struct seq_file *s)
return 0;
}
-static void print_lock(struct seq_file *s, struct dlm_lkb *lkb, struct dlm_rsb *r)
+static void print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
+ struct dlm_rsb *r)
{
- unsigned int waiting = 0;
- uint64_t xid = 0;
+ u64 xid = 0;
+ u64 us;
if (lkb->lkb_flags & DLM_IFL_USER) {
if (lkb->lkb_ua)
xid = lkb->lkb_ua->xid;
}
- if (lkb->lkb_timestamp)
- waiting = jiffies_to_msecs(jiffies - lkb->lkb_timestamp);
+ /* microseconds since lkb was added to current queue */
+ us = ktime_to_us(ktime_sub(ktime_get(), lkb->lkb_timestamp));
- /* id nodeid remid pid xid exflags flags sts grmode rqmode time_ms
+ /* id nodeid remid pid xid exflags flags sts grmode rqmode time_us
r_nodeid r_len r_name */
- seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %u %u %d \"%s\"\n",
+ seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %llu %u %d \"%s\"\n",
lkb->lkb_id,
lkb->lkb_nodeid,
lkb->lkb_remid,
@@ -187,26 +188,114 @@ static void print_lock(struct seq_file *s, struct dlm_lkb *lkb, struct dlm_rsb *
lkb->lkb_status,
lkb->lkb_grmode,
lkb->lkb_rqmode,
- waiting,
+ (unsigned long long)us,
r->res_nodeid,
r->res_length,
r->res_name);
}
-static int print_locks(struct dlm_rsb *r, struct seq_file *s)
+static int print_format2(struct dlm_rsb *r, struct seq_file *s)
{
struct dlm_lkb *lkb;
lock_rsb(r);
list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue)
- print_lock(s, lkb, r);
+ print_format2_lock(s, lkb, r);
list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue)
- print_lock(s, lkb, r);
+ print_format2_lock(s, lkb, r);
list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue)
- print_lock(s, lkb, r);
+ print_format2_lock(s, lkb, r);
+
+ unlock_rsb(r);
+ return 0;
+}
+
+static void print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb,
+ int rsb_lookup)
+{
+ u64 xid = 0;
+
+ if (lkb->lkb_flags & DLM_IFL_USER) {
+ if (lkb->lkb_ua)
+ xid = lkb->lkb_ua->xid;
+ }
+
+ seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu\n",
+ lkb->lkb_id,
+ lkb->lkb_nodeid,
+ lkb->lkb_remid,
+ lkb->lkb_ownpid,
+ (unsigned long long)xid,
+ lkb->lkb_exflags,
+ lkb->lkb_flags,
+ lkb->lkb_status,
+ lkb->lkb_grmode,
+ lkb->lkb_rqmode,
+ lkb->lkb_highbast,
+ rsb_lookup,
+ lkb->lkb_wait_type,
+ lkb->lkb_lvbseq,
+ (unsigned long long)ktime_to_ns(lkb->lkb_timestamp),
+ (unsigned long long)ktime_to_ns(lkb->lkb_time_bast));
+}
+
+static int print_format3(struct dlm_rsb *r, struct seq_file *s)
+{
+ struct dlm_lkb *lkb;
+ int i, lvblen = r->res_ls->ls_lvblen;
+ int print_name = 1;
+
+ lock_rsb(r);
+
+ seq_printf(s, "rsb %p %d %x %lx %d %d %u %d ",
+ r,
+ r->res_nodeid,
+ r->res_first_lkid,
+ r->res_flags,
+ !list_empty(&r->res_root_list),
+ !list_empty(&r->res_recover_list),
+ r->res_recover_locks_count,
+ r->res_length);
+
+ for (i = 0; i < r->res_length; i++) {
+ if (!isascii(r->res_name[i]) || !isprint(r->res_name[i]))
+ print_name = 0;
+ }
+
+ seq_printf(s, "%s", print_name ? "str " : "hex");
+
+ for (i = 0; i < r->res_length; i++) {
+ if (print_name)
+ seq_printf(s, "%c", r->res_name[i]);
+ else
+ seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
+ }
+ seq_printf(s, "\n");
+
+ if (!r->res_lvbptr)
+ goto do_locks;
+
+ seq_printf(s, "lvb %u %d", r->res_lvbseq, lvblen);
+
+ for (i = 0; i < lvblen; i++)
+ seq_printf(s, " %02x", (unsigned char)r->res_lvbptr[i]);
+ seq_printf(s, "\n");
+
+ do_locks:
+ list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue)
+ print_format3_lock(s, lkb, 0);
+
+ list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue)
+ print_format3_lock(s, lkb, 0);
+
+ list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue)
+ print_format3_lock(s, lkb, 0);
+
+ list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup)
+ print_format3_lock(s, lkb, 1);
unlock_rsb(r);
return 0;
@@ -231,7 +320,7 @@ static int rsb_iter_next(struct rsb_iter *ri)
break;
}
read_unlock(&ls->ls_rsbtbl[i].lock);
- }
+ }
ri->entry = i;
if (ri->entry >= ls->ls_rsbtbl_size)
@@ -248,7 +337,7 @@ static int rsb_iter_next(struct rsb_iter *ri)
read_unlock(&ls->ls_rsbtbl[i].lock);
dlm_put_rsb(old);
goto top;
- }
+ }
ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain);
dlm_hold_rsb(ri->rsb);
read_unlock(&ls->ls_rsbtbl[i].lock);
@@ -274,6 +363,7 @@ static struct rsb_iter *rsb_iter_init(struct dlm_ls *ls)
ri->ls = ls;
ri->entry = 0;
ri->next = NULL;
+ ri->format = 1;
if (rsb_iter_next(ri)) {
rsb_iter_free(ri);
@@ -325,16 +415,26 @@ static int rsb_seq_show(struct seq_file *file, void *iter_ptr)
{
struct rsb_iter *ri = iter_ptr;
- if (ri->locks) {
+ switch (ri->format) {
+ case 1:
+ print_format1(ri->rsb, file);
+ break;
+ case 2:
if (ri->header) {
- seq_printf(file, "id nodeid remid pid xid exflags flags "
- "sts grmode rqmode time_ms r_nodeid "
- "r_len r_name\n");
+ seq_printf(file, "id nodeid remid pid xid exflags "
+ "flags sts grmode rqmode time_ms "
+ "r_nodeid r_len r_name\n");
ri->header = 0;
}
- print_locks(ri->rsb, file);
- } else {
- print_resource(ri->rsb, file);
+ print_format2(ri->rsb, file);
+ break;
+ case 3:
+ if (ri->header) {
+ seq_printf(file, "version rsb 1.1 lvb 1.1 lkb 1.1\n");
+ ri->header = 0;
+ }
+ print_format3(ri->rsb, file);
+ break;
}
return 0;
@@ -385,7 +485,7 @@ static struct rsb_iter *locks_iter_init(struct dlm_ls *ls, loff_t *pos)
ri->ls = ls;
ri->entry = 0;
ri->next = NULL;
- ri->locks = 1;
+ ri->format = 2;
if (*pos == 0)
ri->header = 1;
@@ -448,6 +548,84 @@ static const struct file_operations locks_fops = {
};
/*
+ * Dump all rsb/lvb/lkb state in compact listing, more complete than _locks
+ * This can replace both formats 1 and 2 eventually.
+ */
+
+static struct rsb_iter *all_iter_init(struct dlm_ls *ls, loff_t *pos)
+{
+ struct rsb_iter *ri;
+
+ ri = kzalloc(sizeof *ri, GFP_KERNEL);
+ if (!ri)
+ return NULL;
+
+ ri->ls = ls;
+ ri->entry = 0;
+ ri->next = NULL;
+ ri->format = 3;
+
+ if (*pos == 0)
+ ri->header = 1;
+
+ if (rsb_iter_next(ri)) {
+ rsb_iter_free(ri);
+ return NULL;
+ }
+
+ return ri;
+}
+
+static void *all_seq_start(struct seq_file *file, loff_t *pos)
+{
+ struct rsb_iter *ri;
+ loff_t n = *pos;
+
+ ri = all_iter_init(file->private, pos);
+ if (!ri)
+ return NULL;
+
+ while (n--) {
+ if (rsb_iter_next(ri)) {
+ rsb_iter_free(ri);
+ return NULL;
+ }
+ }
+
+ return ri;
+}
+
+static struct seq_operations all_seq_ops = {
+ .start = all_seq_start,
+ .next = rsb_seq_next,
+ .stop = rsb_seq_stop,
+ .show = rsb_seq_show,
+};
+
+static int all_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ int ret;
+
+ ret = seq_open(file, &all_seq_ops);
+ if (ret)
+ return ret;
+
+ seq = file->private_data;
+ seq->private = inode->i_private;
+
+ return 0;
+}
+
+static const struct file_operations all_fops = {
+ .owner = THIS_MODULE,
+ .open = all_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release
+};
+
+/*
* dump lkb's on the ls_waiters list
*/
@@ -489,30 +667,33 @@ static const struct file_operations waiters_fops = {
.read = waiters_read
};
+void dlm_delete_debug_file(struct dlm_ls *ls)
+{
+ if (ls->ls_debug_rsb_dentry)
+ debugfs_remove(ls->ls_debug_rsb_dentry);
+ if (ls->ls_debug_waiters_dentry)
+ debugfs_remove(ls->ls_debug_waiters_dentry);
+ if (ls->ls_debug_locks_dentry)
+ debugfs_remove(ls->ls_debug_locks_dentry);
+ if (ls->ls_debug_all_dentry)
+ debugfs_remove(ls->ls_debug_all_dentry);
+}
+
int dlm_create_debug_file(struct dlm_ls *ls)
{
char name[DLM_LOCKSPACE_LEN+8];
+ /* format 1 */
+
ls->ls_debug_rsb_dentry = debugfs_create_file(ls->ls_name,
S_IFREG | S_IRUGO,
dlm_root,
ls,
&rsb_fops);
if (!ls->ls_debug_rsb_dentry)
- return -ENOMEM;
+ goto fail;
- memset(name, 0, sizeof(name));
- snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_waiters", ls->ls_name);
-
- ls->ls_debug_waiters_dentry = debugfs_create_file(name,
- S_IFREG | S_IRUGO,
- dlm_root,
- ls,
- &waiters_fops);
- if (!ls->ls_debug_waiters_dentry) {
- debugfs_remove(ls->ls_debug_rsb_dentry);
- return -ENOMEM;
- }
+ /* format 2 */
memset(name, 0, sizeof(name));
snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_locks", ls->ls_name);
@@ -522,23 +703,38 @@ int dlm_create_debug_file(struct dlm_ls *ls)
dlm_root,
ls,
&locks_fops);
- if (!ls->ls_debug_locks_dentry) {
- debugfs_remove(ls->ls_debug_waiters_dentry);
- debugfs_remove(ls->ls_debug_rsb_dentry);
- return -ENOMEM;
- }
+ if (!ls->ls_debug_locks_dentry)
+ goto fail;
+
+ /* format 3 */
+
+ memset(name, 0, sizeof(name));
+ snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_all", ls->ls_name);
+
+ ls->ls_debug_all_dentry = debugfs_create_file(name,
+ S_IFREG | S_IRUGO,
+ dlm_root,
+ ls,
+ &all_fops);
+ if (!ls->ls_debug_all_dentry)
+ goto fail;
+
+ memset(name, 0, sizeof(name));
+ snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_waiters", ls->ls_name);
+
+ ls->ls_debug_waiters_dentry = debugfs_create_file(name,
+ S_IFREG | S_IRUGO,
+ dlm_root,
+ ls,
+ &waiters_fops);
+ if (!ls->ls_debug_waiters_dentry)
+ goto fail;
return 0;
-}
-void dlm_delete_debug_file(struct dlm_ls *ls)
-{
- if (ls->ls_debug_rsb_dentry)
- debugfs_remove(ls->ls_debug_rsb_dentry);
- if (ls->ls_debug_waiters_dentry)
- debugfs_remove(ls->ls_debug_waiters_dentry);
- if (ls->ls_debug_locks_dentry)
- debugfs_remove(ls->ls_debug_locks_dentry);
+ fail:
+ dlm_delete_debug_file(ls);
+ return -ENOMEM;
}
int __init dlm_register_debugfs(void)
diff --git a/fs/dlm/dir.c b/fs/dlm/dir.c
index 85defeb64df..92969f879a1 100644
--- a/fs/dlm/dir.c
+++ b/fs/dlm/dir.c
@@ -374,7 +374,7 @@ void dlm_copy_master_names(struct dlm_ls *ls, char *inbuf, int inlen,
struct list_head *list;
struct dlm_rsb *r;
int offset = 0, dir_nodeid;
- uint16_t be_namelen;
+ __be16 be_namelen;
down_read(&ls->ls_root_sem);
@@ -410,15 +410,15 @@ void dlm_copy_master_names(struct dlm_ls *ls, char *inbuf, int inlen,
if (offset + sizeof(uint16_t)*2 + r->res_length > outlen) {
/* Write end-of-block record */
- be_namelen = 0;
- memcpy(outbuf + offset, &be_namelen, sizeof(uint16_t));
- offset += sizeof(uint16_t);
+ be_namelen = cpu_to_be16(0);
+ memcpy(outbuf + offset, &be_namelen, sizeof(__be16));
+ offset += sizeof(__be16);
goto out;
}
be_namelen = cpu_to_be16(r->res_length);
- memcpy(outbuf + offset, &be_namelen, sizeof(uint16_t));
- offset += sizeof(uint16_t);
+ memcpy(outbuf + offset, &be_namelen, sizeof(__be16));
+ offset += sizeof(__be16);
memcpy(outbuf + offset, r->res_name, r->res_length);
offset += r->res_length;
}
@@ -430,9 +430,9 @@ void dlm_copy_master_names(struct dlm_ls *ls, char *inbuf, int inlen,
if ((list == &ls->ls_root_list) &&
(offset + sizeof(uint16_t) <= outlen)) {
- be_namelen = 0xFFFF;
- memcpy(outbuf + offset, &be_namelen, sizeof(uint16_t));
- offset += sizeof(uint16_t);
+ be_namelen = cpu_to_be16(0xFFFF);
+ memcpy(outbuf + offset, &be_namelen, sizeof(__be16));
+ offset += sizeof(__be16);
}
out:
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
index 868e4c9ef12..ef2f1e35396 100644
--- a/fs/dlm/dlm_internal.h
+++ b/fs/dlm/dlm_internal.h
@@ -245,7 +245,8 @@ struct dlm_lkb {
struct list_head lkb_astqueue; /* need ast to be sent */
struct list_head lkb_ownqueue; /* list of locks for a process */
struct list_head lkb_time_list;
- unsigned long lkb_timestamp;
+ ktime_t lkb_time_bast; /* for debugging */
+ ktime_t lkb_timestamp;
unsigned long lkb_timeout_cs;
char *lkb_lvbptr;
@@ -481,6 +482,7 @@ struct dlm_ls {
struct dentry *ls_debug_rsb_dentry; /* debugfs */
struct dentry *ls_debug_waiters_dentry; /* debugfs */
struct dentry *ls_debug_locks_dentry; /* debugfs */
+ struct dentry *ls_debug_all_dentry; /* debugfs */
wait_queue_head_t ls_uevent_wait; /* user part of join/leave */
int ls_uevent_result;
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index 724ddac9153..6cfe65bbf4a 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -307,7 +307,7 @@ static void queue_cast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv)
lkb->lkb_lksb->sb_status = rv;
lkb->lkb_lksb->sb_flags = lkb->lkb_sbflags;
- dlm_add_ast(lkb, AST_COMP);
+ dlm_add_ast(lkb, AST_COMP, 0);
}
static inline void queue_cast_overlap(struct dlm_rsb *r, struct dlm_lkb *lkb)
@@ -318,12 +318,12 @@ static inline void queue_cast_overlap(struct dlm_rsb *r, struct dlm_lkb *lkb)
static void queue_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rqmode)
{
+ lkb->lkb_time_bast = ktime_get();
+
if (is_master_copy(lkb))
send_bast(r, lkb, rqmode);
- else {
- lkb->lkb_bastmode = rqmode;
- dlm_add_ast(lkb, AST_BAST);
- }
+ else
+ dlm_add_ast(lkb, AST_BAST, rqmode);
}
/*
@@ -744,6 +744,8 @@ static void add_lkb(struct dlm_rsb *r, struct dlm_lkb *lkb, int status)
DLM_ASSERT(!lkb->lkb_status, dlm_print_lkb(lkb););
+ lkb->lkb_timestamp = ktime_get();
+
lkb->lkb_status = status;
switch (status) {
@@ -1013,10 +1015,8 @@ static void add_timeout(struct dlm_lkb *lkb)
{
struct dlm_ls *ls = lkb->lkb_resource->res_ls;
- if (is_master_copy(lkb)) {
- lkb->lkb_timestamp = jiffies;
+ if (is_master_copy(lkb))
return;
- }
if (test_bit(LSFL_TIMEWARN, &ls->ls_flags) &&
!(lkb->lkb_exflags & DLM_LKF_NODLCKWT)) {
@@ -1031,7 +1031,6 @@ static void add_timeout(struct dlm_lkb *lkb)
DLM_ASSERT(list_empty(&lkb->lkb_time_list), dlm_print_lkb(lkb););
mutex_lock(&ls->ls_timeout_mutex);
hold_lkb(lkb);
- lkb->lkb_timestamp = jiffies;
list_add_tail(&lkb->lkb_time_list, &ls->ls_timeout);
mutex_unlock(&ls->ls_timeout_mutex);
}
@@ -1059,6 +1058,7 @@ void dlm_scan_timeout(struct dlm_ls *ls)
struct dlm_rsb *r;
struct dlm_lkb *lkb;
int do_cancel, do_warn;
+ s64 wait_us;
for (;;) {
if (dlm_locking_stopped(ls))
@@ -1069,14 +1069,15 @@ void dlm_scan_timeout(struct dlm_ls *ls)
mutex_lock(&ls->ls_timeout_mutex);
list_for_each_entry(lkb, &ls->ls_timeout, lkb_time_list) {
+ wait_us = ktime_to_us(ktime_sub(ktime_get(),
+ lkb->lkb_timestamp));
+
if ((lkb->lkb_exflags & DLM_LKF_TIMEOUT) &&
- time_after_eq(jiffies, lkb->lkb_timestamp +
- lkb->lkb_timeout_cs * HZ/100))
+ wait_us >= (lkb->lkb_timeout_cs * 10000))
do_cancel = 1;
if ((lkb->lkb_flags & DLM_IFL_WATCH_TIMEWARN) &&
- time_after_eq(jiffies, lkb->lkb_timestamp +
- dlm_config.ci_timewarn_cs * HZ/100))
+ wait_us >= dlm_config.ci_timewarn_cs * 10000)
do_warn = 1;
if (!do_cancel && !do_warn)
@@ -1122,12 +1123,12 @@ void dlm_scan_timeout(struct dlm_ls *ls)
void dlm_adjust_timeouts(struct dlm_ls *ls)
{
struct dlm_lkb *lkb;
- long adj = jiffies - ls->ls_recover_begin;
+ u64 adj_us = jiffies_to_usecs(jiffies - ls->ls_recover_begin);
ls->ls_recover_begin = 0;
mutex_lock(&ls->ls_timeout_mutex);
list_for_each_entry(lkb, &ls->ls_timeout, lkb_time_list)
- lkb->lkb_timestamp += adj;
+ lkb->lkb_timestamp = ktime_add_us(lkb->lkb_timestamp, adj_us);
mutex_unlock(&ls->ls_timeout_mutex);
}
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 3962262f991..103a5ebd137 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -295,6 +295,7 @@ static int add_sock(struct socket *sock, struct connection *con)
con->sock->sk->sk_write_space = lowcomms_write_space;
con->sock->sk->sk_state_change = lowcomms_state_change;
con->sock->sk->sk_user_data = con;
+ con->sock->sk->sk_allocation = GFP_NOFS;
return 0;
}
@@ -823,7 +824,6 @@ static void sctp_init_assoc(struct connection *con)
len = e->len;
offset = e->offset;
spin_unlock(&con->writequeue_lock);
- kmap(e->page);
/* Send the first block off the write queue */
iov[0].iov_base = page_address(e->page)+offset;
@@ -854,7 +854,6 @@ static void sctp_init_assoc(struct connection *con)
if (e->len == 0 && e->users == 0) {
list_del(&e->list);
- kunmap(e->page);
free_entry(e);
}
spin_unlock(&con->writequeue_lock);
@@ -1203,8 +1202,6 @@ void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc)
if (e) {
got_one:
- if (users == 0)
- kmap(e->page);
*ppc = page_address(e->page) + offset;
return e;
}
@@ -1233,7 +1230,6 @@ void dlm_lowcomms_commit_buffer(void *mh)
if (users)
goto out;
e->len = e->end - e->offset;
- kunmap(e->page);
spin_unlock(&con->writequeue_lock);
if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags)) {
@@ -1272,7 +1268,6 @@ static void send_to_sock(struct connection *con)
offset = e->offset;
BUG_ON(len == 0 && e->users == 0);
spin_unlock(&con->writequeue_lock);
- kmap(e->page);
ret = 0;
if (len) {
@@ -1294,7 +1289,6 @@ static void send_to_sock(struct connection *con)
if (e->len == 0 && e->users == 0) {
list_del(&e->list);
- kunmap(e->page);
free_entry(e);
continue;
}
diff --git a/fs/dlm/memory.c b/fs/dlm/memory.c
index 54c14c6d06c..c1775b84eba 100644
--- a/fs/dlm/memory.c
+++ b/fs/dlm/memory.c
@@ -39,7 +39,7 @@ char *dlm_allocate_lvb(struct dlm_ls *ls)
{
char *p;
- p = kzalloc(ls->ls_lvblen, GFP_KERNEL);
+ p = kzalloc(ls->ls_lvblen, ls->ls_allocation);
return p;
}
@@ -57,7 +57,7 @@ struct dlm_rsb *dlm_allocate_rsb(struct dlm_ls *ls, int namelen)
DLM_ASSERT(namelen <= DLM_RESNAME_MAXLEN,);
- r = kzalloc(sizeof(*r) + namelen, GFP_KERNEL);
+ r = kzalloc(sizeof(*r) + namelen, ls->ls_allocation);
return r;
}
@@ -72,7 +72,7 @@ struct dlm_lkb *dlm_allocate_lkb(struct dlm_ls *ls)
{
struct dlm_lkb *lkb;
- lkb = kmem_cache_zalloc(lkb_cache, GFP_KERNEL);
+ lkb = kmem_cache_zalloc(lkb_cache, ls->ls_allocation);
return lkb;
}
diff --git a/fs/dlm/midcomms.c b/fs/dlm/midcomms.c
index 07ac709f3ed..f3396c622ae 100644
--- a/fs/dlm/midcomms.c
+++ b/fs/dlm/midcomms.c
@@ -112,7 +112,7 @@ int dlm_process_incoming_buffer(int nodeid, const void *base,
ordinary messages). */
if (msglen > sizeof(__tmp) && p == &__tmp.p) {
- p = kmalloc(dlm_config.ci_buffer_size, GFP_KERNEL);
+ p = kmalloc(dlm_config.ci_buffer_size, GFP_NOFS);
if (p == NULL)
return ret;
}
diff --git a/fs/dlm/netlink.c b/fs/dlm/netlink.c
index aa2a5775a02..ccc9d62c462 100644
--- a/fs/dlm/netlink.c
+++ b/fs/dlm/netlink.c
@@ -115,7 +115,6 @@ static void fill_data(struct dlm_lock_data *data, struct dlm_lkb *lkb)
data->status = lkb->lkb_status;
data->grmode = lkb->lkb_grmode;
data->rqmode = lkb->lkb_rqmode;
- data->timestamp = lkb->lkb_timestamp;
if (lkb->lkb_ua)
data->xid = lkb->lkb_ua->xid;
if (r) {
diff --git a/fs/dlm/user.c b/fs/dlm/user.c
index b3832c67194..065149e84f4 100644
--- a/fs/dlm/user.c
+++ b/fs/dlm/user.c
@@ -175,7 +175,7 @@ static int lkb_is_endoflife(struct dlm_lkb *lkb, int sb_status, int type)
/* we could possibly check if the cancel of an orphan has resulted in the lkb
being removed and then remove that lkb from the orphans list and free it */
-void dlm_user_add_ast(struct dlm_lkb *lkb, int type)
+void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int bastmode)
{
struct dlm_ls *ls;
struct dlm_user_args *ua;
@@ -208,6 +208,8 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type)
ast_type = lkb->lkb_ast_type;
lkb->lkb_ast_type |= type;
+ if (bastmode)
+ lkb->lkb_bastmode = bastmode;
if (!ast_type) {
kref_get(&lkb->lkb_ref);
diff --git a/fs/dlm/user.h b/fs/dlm/user.h
index 35eb6a13d61..1c968649228 100644
--- a/fs/dlm/user.h
+++ b/fs/dlm/user.h
@@ -9,7 +9,7 @@
#ifndef __USER_DOT_H__
#define __USER_DOT_H__
-void dlm_user_add_ast(struct dlm_lkb *lkb, int type);
+void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int bastmode);
int dlm_user_init(void);
void dlm_user_exit(void);
int dlm_device_deregister(struct dlm_ls *ls);
diff --git a/fs/dquot.c b/fs/dquot.c
index c237ccc8581..61bfff64e5a 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -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;
@@ -647,15 +697,33 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type)
}
/*
+ * 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)
{
@@ -1823,6 +1919,50 @@ int vfs_quota_on(struct super_block *sb, int type, int format_id, char *name,
}
/*
+ * 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);
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index eb3dc4c7ac0..71383437122 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -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)
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 5e78fc17988..0111906a887 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -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;
}
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 04d7b3fa1ac..46cec2b6979 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -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;
diff --git a/fs/exec.c b/fs/exec.c
index 3ef9cf9b187..9c33f542dc7 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -51,6 +51,7 @@
#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>
@@ -132,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;
@@ -684,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);
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index c4bdccf976b..5fa453b49a6 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -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;
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 297ea8dfac7..1dd2abe6313 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -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);
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index f6c94f232ec..c22d01467bd 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -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;
diff --git a/fs/ext4/ext4_sb.h b/fs/ext4/ext4_sb.h
index 445fde603df..b21f16713db 100644
--- a/fs/ext4/ext4_sb.h
+++ b/fs/ext4/ext4_sb.h
@@ -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 */
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 7c3325e0b00..6702a49992a 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -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;
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index da98a9012fa..9fd2a5e1be4 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -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);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 04158ad74db..9494bb24939 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -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;
diff --git a/fs/filesystems.c b/fs/filesystems.c
index d0e20ced62d..d488dcd7f2b 100644
--- a/fs/filesystems.c
+++ b/fs/filesystems.c
@@ -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);
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 34930a964b8..4c9ee701126 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -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;
diff --git a/fs/gfs2/Makefile b/fs/gfs2/Makefile
index ec65851ec80..c1b4ec6a965 100644
--- a/fs/gfs2/Makefile
+++ b/fs/gfs2/Makefile
@@ -1,5 +1,5 @@
obj-$(CONFIG_GFS2_FS) += gfs2.o
-gfs2-y := acl.o bmap.o daemon.o dir.o eaops.o eattr.o glock.o \
+gfs2-y := acl.o bmap.o dir.o eaops.o eattr.o glock.o \
glops.o inode.o log.o lops.o locking.o main.o meta_io.o \
mount.o ops_address.o ops_dentry.o ops_export.o ops_file.o \
ops_fstype.o ops_inode.o ops_super.o quota.o \
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index 3e9bd46f27e..e335dceb6a4 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -91,7 +91,7 @@ static int acl_get(struct gfs2_inode *ip, int access, struct posix_acl **acl,
struct gfs2_ea_location el_this;
int error;
- if (!ip->i_di.di_eattr)
+ if (!ip->i_eattr)
return 0;
memset(&er, 0, sizeof(struct gfs2_ea_request));
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index bec76b1c2bb..11ffc56f1f8 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -75,9 +75,9 @@ static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh,
void *kaddr = kmap(page);
memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode),
- ip->i_di.di_size);
- memset(kaddr + ip->i_di.di_size, 0,
- PAGE_CACHE_SIZE - ip->i_di.di_size);
+ ip->i_disksize);
+ memset(kaddr + ip->i_disksize, 0,
+ PAGE_CACHE_SIZE - ip->i_disksize);
kunmap(page);
SetPageUptodate(page);
@@ -132,7 +132,7 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
if (error)
goto out;
- if (ip->i_di.di_size) {
+ if (ip->i_disksize) {
/* Get a free block, fill it with the stuffed data,
and write it out to disk */
@@ -159,7 +159,7 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
di = (struct gfs2_dinode *)dibh->b_data;
gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
- if (ip->i_di.di_size) {
+ if (ip->i_disksize) {
*(__be64 *)(di + 1) = cpu_to_be64(block);
gfs2_add_inode_blocks(&ip->i_inode, 1);
di->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode));
@@ -926,7 +926,7 @@ static int do_grow(struct gfs2_inode *ip, u64 size)
}
}
- ip->i_di.di_size = size;
+ ip->i_disksize = size;
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
@@ -1033,7 +1033,7 @@ static int trunc_start(struct gfs2_inode *ip, u64 size)
goto out;
if (gfs2_is_stuffed(ip)) {
- ip->i_di.di_size = size;
+ ip->i_disksize = size;
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
@@ -1045,9 +1045,9 @@ static int trunc_start(struct gfs2_inode *ip, u64 size)
error = gfs2_block_truncate_page(ip->i_inode.i_mapping);
if (!error) {
- ip->i_di.di_size = size;
+ ip->i_disksize = size;
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
- ip->i_di.di_flags |= GFS2_DIF_TRUNC_IN_PROG;
+ ip->i_diskflags |= GFS2_DIF_TRUNC_IN_PROG;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
}
@@ -1114,13 +1114,13 @@ static int trunc_end(struct gfs2_inode *ip)
if (error)
goto out;
- if (!ip->i_di.di_size) {
+ if (!ip->i_disksize) {
ip->i_height = 0;
ip->i_goal = ip->i_no_addr;
gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
}
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
- ip->i_di.di_flags &= ~GFS2_DIF_TRUNC_IN_PROG;
+ ip->i_diskflags &= ~GFS2_DIF_TRUNC_IN_PROG;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
@@ -1205,9 +1205,9 @@ int gfs2_truncatei(struct gfs2_inode *ip, u64 size)
if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), S_ISREG(ip->i_inode.i_mode)))
return -EINVAL;
- if (size > ip->i_di.di_size)
+ if (size > ip->i_disksize)
error = do_grow(ip, size);
- else if (size < ip->i_di.di_size)
+ else if (size < ip->i_disksize)
error = do_shrink(ip, size);
else
/* update time stamps */
@@ -1219,7 +1219,7 @@ int gfs2_truncatei(struct gfs2_inode *ip, u64 size)
int gfs2_truncatei_resume(struct gfs2_inode *ip)
{
int error;
- error = trunc_dealloc(ip, ip->i_di.di_size);
+ error = trunc_dealloc(ip, ip->i_disksize);
if (!error)
error = trunc_end(ip);
return error;
@@ -1231,35 +1231,6 @@ int gfs2_file_dealloc(struct gfs2_inode *ip)
}
/**
- * gfs2_write_calc_reserv - calculate number of blocks needed to write to a file
- * @ip: the file
- * @len: the number of bytes to be written to the file
- * @data_blocks: returns the number of data blocks required
- * @ind_blocks: returns the number of indirect blocks required
- *
- */
-
-void gfs2_write_calc_reserv(struct gfs2_inode *ip, unsigned int len,
- unsigned int *data_blocks, unsigned int *ind_blocks)
-{
- struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
- unsigned int tmp;
-
- if (gfs2_is_dir(ip)) {
- *data_blocks = DIV_ROUND_UP(len, sdp->sd_jbsize) + 2;
- *ind_blocks = 3 * (sdp->sd_max_jheight - 1);
- } else {
- *data_blocks = (len >> sdp->sd_sb.sb_bsize_shift) + 3;
- *ind_blocks = 3 * (sdp->sd_max_height - 1);
- }
-
- for (tmp = *data_blocks; tmp > sdp->sd_diptrs;) {
- tmp = DIV_ROUND_UP(tmp, sdp->sd_inptrs);
- *ind_blocks += tmp;
- }
-}
-
-/**
* gfs2_write_alloc_required - figure out if a write will require an allocation
* @ip: the file being written to
* @offset: the offset to write to
@@ -1276,6 +1247,7 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
struct buffer_head bh;
unsigned int shift;
u64 lblock, lblock_stop, size;
+ u64 end_of_file;
*alloc_required = 0;
@@ -1291,19 +1263,12 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
*alloc_required = 1;
shift = sdp->sd_sb.sb_bsize_shift;
- if (gfs2_is_dir(ip)) {
- unsigned int bsize = sdp->sd_jbsize;
- lblock = offset;
- do_div(lblock, bsize);
- lblock_stop = offset + len + bsize - 1;
- do_div(lblock_stop, bsize);
- } else {
- u64 end_of_file = (ip->i_di.di_size + sdp->sd_sb.sb_bsize - 1) >> shift;
- lblock = offset >> shift;
- lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift;
- if (lblock_stop > end_of_file)
- return 0;
- }
+ BUG_ON(gfs2_is_dir(ip));
+ end_of_file = (ip->i_disksize + sdp->sd_sb.sb_bsize - 1) >> shift;
+ lblock = offset >> shift;
+ lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift;
+ if (lblock_stop > end_of_file)
+ return 0;
size = (lblock_stop - lblock) << shift;
do {
diff --git a/fs/gfs2/bmap.h b/fs/gfs2/bmap.h
index 4e6cde2943b..c983177e05a 100644
--- a/fs/gfs2/bmap.h
+++ b/fs/gfs2/bmap.h
@@ -10,10 +10,40 @@
#ifndef __BMAP_DOT_H__
#define __BMAP_DOT_H__
+#include "inode.h"
+
struct inode;
struct gfs2_inode;
struct page;
+
+/**
+ * gfs2_write_calc_reserv - calculate number of blocks needed to write to a file
+ * @ip: the file
+ * @len: the number of bytes to be written to the file
+ * @data_blocks: returns the number of data blocks required
+ * @ind_blocks: returns the number of indirect blocks required
+ *
+ */
+
+static inline void gfs2_write_calc_reserv(const struct gfs2_inode *ip,
+ unsigned int len,
+ unsigned int *data_blocks,
+ unsigned int *ind_blocks)
+{
+ const struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+ unsigned int tmp;
+
+ BUG_ON(gfs2_is_dir(ip));
+ *data_blocks = (len >> sdp->sd_sb.sb_bsize_shift) + 3;
+ *ind_blocks = 3 * (sdp->sd_max_height - 1);
+
+ for (tmp = *data_blocks; tmp > sdp->sd_diptrs;) {
+ tmp = DIV_ROUND_UP(tmp, sdp->sd_inptrs);
+ *ind_blocks += tmp;
+ }
+}
+
int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page);
int gfs2_block_map(struct inode *inode, sector_t lblock, struct buffer_head *bh, int create);
int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen);
@@ -21,10 +51,6 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsi
int gfs2_truncatei(struct gfs2_inode *ip, u64 size);
int gfs2_truncatei_resume(struct gfs2_inode *ip);
int gfs2_file_dealloc(struct gfs2_inode *ip);
-
-void gfs2_write_calc_reserv(struct gfs2_inode *ip, unsigned int len,
- unsigned int *data_blocks,
- unsigned int *ind_blocks);
int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
unsigned int len, int *alloc_required);
diff --git a/fs/gfs2/daemon.c b/fs/gfs2/daemon.c
deleted file mode 100644
index e51991947d2..00000000000
--- a/fs/gfs2/daemon.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU General Public License version 2.
- */
-
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-#include <linux/kthread.h>
-#include <linux/delay.h>
-#include <linux/gfs2_ondisk.h>
-#include <linux/lm_interface.h>
-#include <linux/freezer.h>
-
-#include "gfs2.h"
-#include "incore.h"
-#include "daemon.h"
-#include "glock.h"
-#include "log.h"
-#include "quota.h"
-#include "recovery.h"
-#include "super.h"
-#include "util.h"
-
-/* This uses schedule_timeout() instead of msleep() because it's good for
- the daemons to wake up more often than the timeout when unmounting so
- the user's unmount doesn't sit there forever.
-
- The kthread functions used to start these daemons block and flush signals. */
-
-/**
- * gfs2_glockd - Reclaim unused glock structures
- * @sdp: Pointer to GFS2 superblock
- *
- * One or more of these daemons run, reclaiming glocks on sd_reclaim_list.
- * Number of daemons can be set by user, with num_glockd mount option.
- */
-
-int gfs2_glockd(void *data)
-{
- struct gfs2_sbd *sdp = data;
-
- while (!kthread_should_stop()) {
- while (atomic_read(&sdp->sd_reclaim_count))
- gfs2_reclaim_glock(sdp);
-
- wait_event_interruptible(sdp->sd_reclaim_wq,
- (atomic_read(&sdp->sd_reclaim_count) ||
- kthread_should_stop()));
- if (freezing(current))
- refrigerator();
- }
-
- return 0;
-}
-
-/**
- * gfs2_recoverd - Recover dead machine's journals
- * @sdp: Pointer to GFS2 superblock
- *
- */
-
-int gfs2_recoverd(void *data)
-{
- struct gfs2_sbd *sdp = data;
- unsigned long t;
-
- while (!kthread_should_stop()) {
- gfs2_check_journals(sdp);
- t = gfs2_tune_get(sdp, gt_recoverd_secs) * HZ;
- if (freezing(current))
- refrigerator();
- schedule_timeout_interruptible(t);
- }
-
- return 0;
-}
-
-/**
- * gfs2_quotad - Write cached quota changes into the quota file
- * @sdp: Pointer to GFS2 superblock
- *
- */
-
-int gfs2_quotad(void *data)
-{
- struct gfs2_sbd *sdp = data;
- unsigned long t;
- int error;
-
- while (!kthread_should_stop()) {
- /* Update the master statfs file */
-
- t = sdp->sd_statfs_sync_time +
- gfs2_tune_get(sdp, gt_statfs_quantum) * HZ;
-
- if (time_after_eq(jiffies, t)) {
- error = gfs2_statfs_sync(sdp);
- if (error &&
- error != -EROFS &&
- !test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
- fs_err(sdp, "quotad: (1) error=%d\n", error);
- sdp->sd_statfs_sync_time = jiffies;
- }
-
- /* Update quota file */
-
- t = sdp->sd_quota_sync_time +
- gfs2_tune_get(sdp, gt_quota_quantum) * HZ;
-
- if (time_after_eq(jiffies, t)) {
- error = gfs2_quota_sync(sdp);
- if (error &&
- error != -EROFS &&
- !test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
- fs_err(sdp, "quotad: (2) error=%d\n", error);
- sdp->sd_quota_sync_time = jiffies;
- }
-
- gfs2_quota_scan(sdp);
-
- t = gfs2_tune_get(sdp, gt_quotad_secs) * HZ;
- if (freezing(current))
- refrigerator();
- schedule_timeout_interruptible(t);
- }
-
- return 0;
-}
-
diff --git a/fs/gfs2/daemon.h b/fs/gfs2/daemon.h
deleted file mode 100644
index 4be084fb6a6..00000000000
--- a/fs/gfs2/daemon.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU General Public License version 2.
- */
-
-#ifndef __DAEMON_DOT_H__
-#define __DAEMON_DOT_H__
-
-int gfs2_glockd(void *data);
-int gfs2_recoverd(void *data);
-int gfs2_quotad(void *data);
-
-#endif /* __DAEMON_DOT_H__ */
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index eed040d8ba3..b7c8e5c7079 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -36,7 +36,7 @@
* the block. In leaves, they begin at offset sizeof(struct gfs2_leaf) from the
* beginning of the leaf block. The dirents reside in leaves when
*
- * dip->i_di.di_flags & GFS2_DIF_EXHASH is true
+ * dip->i_diskflags & GFS2_DIF_EXHASH is true
*
* Otherwise, the dirents are "linear", within a single stuffed dinode block.
*
@@ -128,8 +128,8 @@ static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf,
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size);
- if (ip->i_di.di_size < offset + size)
- ip->i_di.di_size = offset + size;
+ if (ip->i_disksize < offset + size)
+ ip->i_disksize = offset + size;
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_dinode_out(ip, dibh->b_data);
@@ -226,8 +226,8 @@ out:
if (error)
return error;
- if (ip->i_di.di_size < offset + copied)
- ip->i_di.di_size = offset + copied;
+ if (ip->i_disksize < offset + copied)
+ ip->i_disksize = offset + copied;
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
@@ -277,11 +277,11 @@ static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf, u64 offset,
int copied = 0;
int error = 0;
- if (offset >= ip->i_di.di_size)
+ if (offset >= ip->i_disksize)
return 0;
- if (offset + size > ip->i_di.di_size)
- size = ip->i_di.di_size - offset;
+ if (offset + size > ip->i_disksize)
+ size = ip->i_disksize - offset;
if (!size)
return 0;
@@ -755,12 +755,12 @@ static struct gfs2_dirent *gfs2_dirent_search(struct inode *inode,
struct gfs2_inode *ip = GFS2_I(inode);
int error;
- if (ip->i_di.di_flags & GFS2_DIF_EXHASH) {
+ if (ip->i_diskflags & GFS2_DIF_EXHASH) {
struct gfs2_leaf *leaf;
unsigned hsize = 1 << ip->i_depth;
unsigned index;
u64 ln;
- if (hsize * sizeof(u64) != ip->i_di.di_size) {
+ if (hsize * sizeof(u64) != ip->i_disksize) {
gfs2_consist_inode(ip);
return ERR_PTR(-EIO);
}
@@ -858,8 +858,8 @@ static int dir_make_exhash(struct inode *inode)
return -ENOSPC;
bn = bh->b_blocknr;
- gfs2_assert(sdp, dip->i_di.di_entries < (1 << 16));
- leaf->lf_entries = cpu_to_be16(dip->i_di.di_entries);
+ gfs2_assert(sdp, dip->i_entries < (1 << 16));
+ leaf->lf_entries = cpu_to_be16(dip->i_entries);
/* Copy dirents */
@@ -905,9 +905,9 @@ static int dir_make_exhash(struct inode *inode)
for (x = sdp->sd_hash_ptrs; x--; lp++)
*lp = cpu_to_be64(bn);
- dip->i_di.di_size = sdp->sd_sb.sb_bsize / 2;
+ dip->i_disksize = sdp->sd_sb.sb_bsize / 2;
gfs2_add_inode_blocks(&dip->i_inode, 1);
- dip->i_di.di_flags |= GFS2_DIF_EXHASH;
+ dip->i_diskflags |= GFS2_DIF_EXHASH;
for (x = sdp->sd_hash_ptrs, y = -1; x; x >>= 1, y++) ;
dip->i_depth = y;
@@ -1082,7 +1082,7 @@ static int dir_double_exhash(struct gfs2_inode *dip)
int error = 0;
hsize = 1 << dip->i_depth;
- if (hsize * sizeof(u64) != dip->i_di.di_size) {
+ if (hsize * sizeof(u64) != dip->i_disksize) {
gfs2_consist_inode(dip);
return -EIO;
}
@@ -1091,7 +1091,7 @@ static int dir_double_exhash(struct gfs2_inode *dip)
buf = kcalloc(3, sdp->sd_hash_bsize, GFP_NOFS | __GFP_NOFAIL);
- for (block = dip->i_di.di_size >> sdp->sd_hash_bsize_shift; block--;) {
+ for (block = dip->i_disksize >> sdp->sd_hash_bsize_shift; block--;) {
error = gfs2_dir_read_data(dip, (char *)buf,
block * sdp->sd_hash_bsize,
sdp->sd_hash_bsize, 1);
@@ -1370,7 +1370,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
unsigned depth = 0;
hsize = 1 << dip->i_depth;
- if (hsize * sizeof(u64) != dip->i_di.di_size) {
+ if (hsize * sizeof(u64) != dip->i_disksize) {
gfs2_consist_inode(dip);
return -EIO;
}
@@ -1426,10 +1426,10 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
int copied = 0;
int error;
- if (!dip->i_di.di_entries)
+ if (!dip->i_entries)
return 0;
- if (dip->i_di.di_flags & GFS2_DIF_EXHASH)
+ if (dip->i_diskflags & GFS2_DIF_EXHASH)
return dir_e_read(inode, offset, opaque, filldir);
if (!gfs2_is_stuffed(dip)) {
@@ -1453,17 +1453,17 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
error = PTR_ERR(dent);
goto out;
}
- if (dip->i_di.di_entries != g.offset) {
+ if (dip->i_entries != g.offset) {
fs_warn(sdp, "Number of entries corrupt in dir %llu, "
- "ip->i_di.di_entries (%u) != g.offset (%u)\n",
+ "ip->i_entries (%u) != g.offset (%u)\n",
(unsigned long long)dip->i_no_addr,
- dip->i_di.di_entries,
+ dip->i_entries,
g.offset);
error = -EIO;
goto out;
}
error = do_filldir_main(dip, offset, opaque, filldir, darr,
- dip->i_di.di_entries, &copied);
+ dip->i_entries, &copied);
out:
kfree(darr);
}
@@ -1612,7 +1612,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
dent = gfs2_init_dirent(inode, dent, name, bh);
gfs2_inum_out(nip, dent);
dent->de_type = cpu_to_be16(type);
- if (ip->i_di.di_flags & GFS2_DIF_EXHASH) {
+ if (ip->i_diskflags & GFS2_DIF_EXHASH) {
leaf = (struct gfs2_leaf *)bh->b_data;
be16_add_cpu(&leaf->lf_entries, 1);
}
@@ -1621,14 +1621,14 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
if (error)
break;
gfs2_trans_add_bh(ip->i_gl, bh, 1);
- ip->i_di.di_entries++;
+ ip->i_entries++;
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_dinode_out(ip, bh->b_data);
brelse(bh);
error = 0;
break;
}
- if (!(ip->i_di.di_flags & GFS2_DIF_EXHASH)) {
+ if (!(ip->i_diskflags & GFS2_DIF_EXHASH)) {
error = dir_make_exhash(inode);
if (error)
break;
@@ -1691,7 +1691,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name)
}
dirent_del(dip, bh, prev, dent);
- if (dip->i_di.di_flags & GFS2_DIF_EXHASH) {
+ if (dip->i_diskflags & GFS2_DIF_EXHASH) {
struct gfs2_leaf *leaf = (struct gfs2_leaf *)bh->b_data;
u16 entries = be16_to_cpu(leaf->lf_entries);
if (!entries)
@@ -1704,10 +1704,10 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name)
if (error)
return error;
- if (!dip->i_di.di_entries)
+ if (!dip->i_entries)
gfs2_consist_inode(dip);
gfs2_trans_add_bh(dip->i_gl, bh, 1);
- dip->i_di.di_entries--;
+ dip->i_entries--;
dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME;
gfs2_dinode_out(dip, bh->b_data);
brelse(bh);
@@ -1748,7 +1748,7 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
gfs2_inum_out(nip, dent);
dent->de_type = cpu_to_be16(new_type);
- if (dip->i_di.di_flags & GFS2_DIF_EXHASH) {
+ if (dip->i_diskflags & GFS2_DIF_EXHASH) {
brelse(bh);
error = gfs2_meta_inode_buffer(dip, &bh);
if (error)
@@ -1784,7 +1784,7 @@ static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data)
int error = 0;
hsize = 1 << dip->i_depth;
- if (hsize * sizeof(u64) != dip->i_di.di_size) {
+ if (hsize * sizeof(u64) != dip->i_disksize) {
gfs2_consist_inode(dip);
return -EIO;
}
diff --git a/fs/gfs2/dir.h b/fs/gfs2/dir.h
index 8a468cac932..4f919440c3b 100644
--- a/fs/gfs2/dir.h
+++ b/fs/gfs2/dir.h
@@ -11,6 +11,7 @@
#define __DIR_DOT_H__
#include <linux/dcache.h>
+#include <linux/crc32.h>
struct inode;
struct gfs2_inode;
diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c
index e3f76f451b0..0d1c76d906a 100644
--- a/fs/gfs2/eattr.c
+++ b/fs/gfs2/eattr.c
@@ -114,11 +114,11 @@ static int ea_foreach(struct gfs2_inode *ip, ea_call_t ea_call, void *data)
__be64 *eablk, *end;
int error;
- error = gfs2_meta_read(ip->i_gl, ip->i_di.di_eattr, DIO_WAIT, &bh);
+ error = gfs2_meta_read(ip->i_gl, ip->i_eattr, DIO_WAIT, &bh);
if (error)
return error;
- if (!(ip->i_di.di_flags & GFS2_DIF_EA_INDIRECT)) {
+ if (!(ip->i_diskflags & GFS2_DIF_EA_INDIRECT)) {
error = ea_foreach_i(ip, bh, ea_call, data);
goto out;
}
@@ -414,7 +414,7 @@ int gfs2_ea_list(struct gfs2_inode *ip, struct gfs2_ea_request *er)
if (error)
return error;
- if (ip->i_di.di_eattr) {
+ if (ip->i_eattr) {
struct ea_list ei = { .ei_er = er, .ei_size = 0 };
error = ea_foreach(ip, ea_list_i, &ei);
@@ -514,7 +514,7 @@ int gfs2_ea_get_i(struct gfs2_inode *ip, struct gfs2_ea_request *er)
struct gfs2_ea_location el;
int error;
- if (!ip->i_di.di_eattr)
+ if (!ip->i_eattr)
return -ENODATA;
error = gfs2_ea_find(ip, er, &el);
@@ -741,7 +741,7 @@ static int ea_init_i(struct gfs2_inode *ip, struct gfs2_ea_request *er,
if (error)
return error;
- ip->i_di.di_eattr = bh->b_blocknr;
+ ip->i_eattr = bh->b_blocknr;
error = ea_write(ip, GFS2_EA_BH2FIRST(bh), er);
brelse(bh);
@@ -935,10 +935,10 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er,
int error;
int mh_size = sizeof(struct gfs2_meta_header);
- if (ip->i_di.di_flags & GFS2_DIF_EA_INDIRECT) {
+ if (ip->i_diskflags & GFS2_DIF_EA_INDIRECT) {
__be64 *end;
- error = gfs2_meta_read(ip->i_gl, ip->i_di.di_eattr, DIO_WAIT,
+ error = gfs2_meta_read(ip->i_gl, ip->i_eattr, DIO_WAIT,
&indbh);
if (error)
return error;
@@ -972,9 +972,9 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er,
gfs2_buffer_clear_tail(indbh, mh_size);
eablk = (__be64 *)(indbh->b_data + mh_size);
- *eablk = cpu_to_be64(ip->i_di.di_eattr);
- ip->i_di.di_eattr = blk;
- ip->i_di.di_flags |= GFS2_DIF_EA_INDIRECT;
+ *eablk = cpu_to_be64(ip->i_eattr);
+ ip->i_eattr = blk;
+ ip->i_diskflags |= GFS2_DIF_EA_INDIRECT;
gfs2_add_inode_blocks(&ip->i_inode, 1);
eablk++;
@@ -1015,7 +1015,7 @@ static int ea_set_i(struct gfs2_inode *ip, struct gfs2_ea_request *er,
if (error)
return error;
- if (!(ip->i_di.di_flags & GFS2_DIF_EA_INDIRECT))
+ if (!(ip->i_diskflags & GFS2_DIF_EA_INDIRECT))
blks++;
if (GFS2_EAREQ_SIZE_STUFFED(er) > GFS2_SB(&ip->i_inode)->sd_jbsize)
blks += DIV_ROUND_UP(er->er_data_len, GFS2_SB(&ip->i_inode)->sd_jbsize);
@@ -1040,7 +1040,7 @@ int gfs2_ea_set_i(struct gfs2_inode *ip, struct gfs2_ea_request *er)
struct gfs2_ea_location el;
int error;
- if (!ip->i_di.di_eattr) {
+ if (!ip->i_eattr) {
if (er->er_flags & XATTR_REPLACE)
return -ENODATA;
return ea_init(ip, er);
@@ -1051,7 +1051,7 @@ int gfs2_ea_set_i(struct gfs2_inode *ip, struct gfs2_ea_request *er)
return error;
if (el.el_ea) {
- if (ip->i_di.di_flags & GFS2_DIF_APPENDONLY) {
+ if (ip->i_diskflags & GFS2_DIF_APPENDONLY) {
brelse(el.el_bh);
return -EPERM;
}
@@ -1145,7 +1145,7 @@ int gfs2_ea_remove_i(struct gfs2_inode *ip, struct gfs2_ea_request *er)
struct gfs2_ea_location el;
int error;
- if (!ip->i_di.di_eattr)
+ if (!ip->i_eattr)
return -ENODATA;
error = gfs2_ea_find(ip, er, &el);
@@ -1309,7 +1309,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
memset(&rlist, 0, sizeof(struct gfs2_rgrp_list));
- error = gfs2_meta_read(ip->i_gl, ip->i_di.di_eattr, DIO_WAIT, &indbh);
+ error = gfs2_meta_read(ip->i_gl, ip->i_eattr, DIO_WAIT, &indbh);
if (error)
return error;
@@ -1388,7 +1388,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
if (bstart)
gfs2_free_meta(ip, bstart, blen);
- ip->i_di.di_flags &= ~GFS2_DIF_EA_INDIRECT;
+ ip->i_diskflags &= ~GFS2_DIF_EA_INDIRECT;
error = gfs2_meta_inode_buffer(ip, &dibh);
if (!error) {
@@ -1416,7 +1416,7 @@ static int ea_dealloc_block(struct gfs2_inode *ip)
struct buffer_head *dibh;
int error;
- rgd = gfs2_blk2rgrpd(sdp, ip->i_di.di_eattr);
+ rgd = gfs2_blk2rgrpd(sdp, ip->i_eattr);
if (!rgd) {
gfs2_consist_inode(ip);
return -EIO;
@@ -1432,9 +1432,9 @@ static int ea_dealloc_block(struct gfs2_inode *ip)
if (error)
goto out_gunlock;
- gfs2_free_meta(ip, ip->i_di.di_eattr, 1);
+ gfs2_free_meta(ip, ip->i_eattr, 1);
- ip->i_di.di_eattr = 0;
+ ip->i_eattr = 0;
gfs2_add_inode_blocks(&ip->i_inode, -1);
error = gfs2_meta_inode_buffer(ip, &dibh);
@@ -1479,7 +1479,7 @@ int gfs2_ea_dealloc(struct gfs2_inode *ip)
if (error)
goto out_rindex;
- if (ip->i_di.di_flags & GFS2_DIF_EA_INDIRECT) {
+ if (ip->i_diskflags & GFS2_DIF_EA_INDIRECT) {
error = ea_dealloc_indirect(ip);
if (error)
goto out_rindex;
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index c962283d4e7..6b983aef785 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -40,6 +40,7 @@
#include "quota.h"
#include "super.h"
#include "util.h"
+#include "bmap.h"
struct gfs2_gl_hash_bucket {
struct hlist_head hb_list;
@@ -61,9 +62,10 @@ static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int
static DECLARE_RWSEM(gfs2_umount_flush_sem);
static struct dentry *gfs2_root;
-static struct task_struct *scand_process;
-static unsigned int scand_secs = 5;
static struct workqueue_struct *glock_workqueue;
+static LIST_HEAD(lru_list);
+static atomic_t lru_count = ATOMIC_INIT(0);
+static DEFINE_SPINLOCK(lru_lock);
#define GFS2_GL_HASH_SHIFT 15
#define GFS2_GL_HASH_SIZE (1 << GFS2_GL_HASH_SHIFT)
@@ -174,6 +176,22 @@ static void gfs2_glock_hold(struct gfs2_glock *gl)
}
/**
+ * gfs2_glock_schedule_for_reclaim - Add a glock to the reclaim list
+ * @gl: the glock
+ *
+ */
+
+static void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl)
+{
+ spin_lock(&lru_lock);
+ if (list_empty(&gl->gl_lru) && gl->gl_state != LM_ST_UNLOCKED) {
+ list_add_tail(&gl->gl_lru, &lru_list);
+ atomic_inc(&lru_count);
+ }
+ spin_unlock(&lru_lock);
+}
+
+/**
* gfs2_glock_put() - Decrement reference count on glock
* @gl: The glock to put
*
@@ -187,14 +205,23 @@ int gfs2_glock_put(struct gfs2_glock *gl)
if (atomic_dec_and_test(&gl->gl_ref)) {
hlist_del(&gl->gl_list);
write_unlock(gl_lock_addr(gl->gl_hash));
+ spin_lock(&lru_lock);
+ if (!list_empty(&gl->gl_lru)) {
+ list_del_init(&gl->gl_lru);
+ atomic_dec(&lru_count);
+ }
+ spin_unlock(&lru_lock);
GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_UNLOCKED);
- GLOCK_BUG_ON(gl, !list_empty(&gl->gl_reclaim));
+ GLOCK_BUG_ON(gl, !list_empty(&gl->gl_lru));
GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders));
glock_free(gl);
rv = 1;
goto out;
}
write_unlock(gl_lock_addr(gl->gl_hash));
+ /* 1 for being hashed, 1 for having state != LM_ST_UNLOCKED */
+ if (atomic_read(&gl->gl_ref) == 2)
+ gfs2_glock_schedule_for_reclaim(gl);
out:
return rv;
}
@@ -289,10 +316,13 @@ static void gfs2_holder_wake(struct gfs2_holder *gh)
* do_promote - promote as many requests as possible on the current queue
* @gl: The glock
*
- * Returns: true if there is a blocked holder at the head of the list
+ * Returns: 1 if there is a blocked holder at the head of the list, or 2
+ * if a type specific operation is underway.
*/
static int do_promote(struct gfs2_glock *gl)
+__releases(&gl->gl_spin)
+__acquires(&gl->gl_spin)
{
const struct gfs2_glock_operations *glops = gl->gl_ops;
struct gfs2_holder *gh, *tmp;
@@ -310,6 +340,8 @@ restart:
ret = glops->go_lock(gh);
spin_lock(&gl->gl_spin);
if (ret) {
+ if (ret == 1)
+ return 2;
gh->gh_error = ret;
list_del_init(&gh->gh_list);
gfs2_holder_wake(gh);
@@ -414,6 +446,7 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret)
const struct gfs2_glock_operations *glops = gl->gl_ops;
struct gfs2_holder *gh;
unsigned state = ret & LM_OUT_ST_MASK;
+ int rv;
spin_lock(&gl->gl_spin);
state_change(gl, state);
@@ -468,7 +501,6 @@ retry:
gfs2_demote_wake(gl);
if (state != LM_ST_UNLOCKED) {
if (glops->go_xmote_bh) {
- int rv;
spin_unlock(&gl->gl_spin);
rv = glops->go_xmote_bh(gl, gh);
if (rv == -EAGAIN)
@@ -479,10 +511,13 @@ retry:
goto out;
}
}
- do_promote(gl);
+ rv = do_promote(gl);
+ if (rv == 2)
+ goto out_locked;
}
out:
clear_bit(GLF_LOCK, &gl->gl_flags);
+out_locked:
spin_unlock(&gl->gl_spin);
gfs2_glock_put(gl);
}
@@ -511,6 +546,8 @@ static unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock,
*/
static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int target)
+__releases(&gl->gl_spin)
+__acquires(&gl->gl_spin)
{
const struct gfs2_glock_operations *glops = gl->gl_ops;
struct gfs2_sbd *sdp = gl->gl_sbd;
@@ -576,8 +613,11 @@ static inline struct gfs2_holder *find_first_holder(const struct gfs2_glock *gl)
*/
static void run_queue(struct gfs2_glock *gl, const int nonblock)
+__releases(&gl->gl_spin)
+__acquires(&gl->gl_spin)
{
struct gfs2_holder *gh = NULL;
+ int ret;
if (test_and_set_bit(GLF_LOCK, &gl->gl_flags))
return;
@@ -596,8 +636,11 @@ static void run_queue(struct gfs2_glock *gl, const int nonblock)
} else {
if (test_bit(GLF_DEMOTE, &gl->gl_flags))
gfs2_demote_wake(gl);
- if (do_promote(gl) == 0)
+ ret = do_promote(gl);
+ if (ret == 0)
goto out;
+ if (ret == 2)
+ return;
gh = find_first_waiter(gl);
gl->gl_target = gh->gh_state;
if (!(gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)))
@@ -820,7 +863,7 @@ static void wait_on_demote(struct gfs2_glock *gl)
*/
static void handle_callback(struct gfs2_glock *gl, unsigned int state,
- int remote, unsigned long delay)
+ unsigned long delay)
{
int bit = delay ? GLF_PENDING_DEMOTE : GLF_DEMOTE;
@@ -828,9 +871,6 @@ static void handle_callback(struct gfs2_glock *gl, unsigned int state,
if (gl->gl_demote_state == LM_ST_EXCLUSIVE) {
gl->gl_demote_state = state;
gl->gl_demote_time = jiffies;
- if (remote && gl->gl_ops->go_type == LM_TYPE_IOPEN &&
- gl->gl_object)
- gfs2_glock_schedule_for_reclaim(gl);
} else if (gl->gl_demote_state != LM_ST_UNLOCKED &&
gl->gl_demote_state != state) {
gl->gl_demote_state = LM_ST_UNLOCKED;
@@ -877,6 +917,8 @@ void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...)
*/
static inline void add_to_queue(struct gfs2_holder *gh)
+__releases(&gl->gl_spin)
+__acquires(&gl->gl_spin)
{
struct gfs2_glock *gl = gh->gh_gl;
struct gfs2_sbd *sdp = gl->gl_sbd;
@@ -998,7 +1040,7 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
spin_lock(&gl->gl_spin);
if (gh->gh_flags & GL_NOCACHE)
- handle_callback(gl, LM_ST_UNLOCKED, 0, 0);
+ handle_callback(gl, LM_ST_UNLOCKED, 0);
list_del_init(&gh->gh_list);
if (find_first_holder(gl) == NULL) {
@@ -1269,12 +1311,26 @@ static void blocking_cb(struct gfs2_sbd *sdp, struct lm_lockname *name,
delay = gl->gl_ops->go_min_hold_time;
spin_lock(&gl->gl_spin);
- handle_callback(gl, state, 1, delay);
+ handle_callback(gl, state, delay);
spin_unlock(&gl->gl_spin);
if (queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0)
gfs2_glock_put(gl);
}
+static void gfs2_jdesc_make_dirty(struct gfs2_sbd *sdp, unsigned int jid)
+{
+ struct gfs2_jdesc *jd;
+
+ spin_lock(&sdp->sd_jindex_spin);
+ list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) {
+ if (jd->jd_jid != jid)
+ continue;
+ jd->jd_dirty = 1;
+ break;
+ }
+ spin_unlock(&sdp->sd_jindex_spin);
+}
+
/**
* gfs2_glock_cb - Callback used by locking module
* @sdp: Pointer to the superblock
@@ -1338,80 +1394,83 @@ void gfs2_glock_cb(void *cb_data, unsigned int type, void *data)
* Returns: 1 if it's ok
*/
-static int demote_ok(struct gfs2_glock *gl)
+static int demote_ok(const struct gfs2_glock *gl)
{
const struct gfs2_glock_operations *glops = gl->gl_ops;
- int demote = 1;
-
- if (test_bit(GLF_STICKY, &gl->gl_flags))
- demote = 0;
- else if (glops->go_demote_ok)
- demote = glops->go_demote_ok(gl);
-
- return demote;
-}
-
-/**
- * gfs2_glock_schedule_for_reclaim - Add a glock to the reclaim list
- * @gl: the glock
- *
- */
-
-void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl)
-{
- struct gfs2_sbd *sdp = gl->gl_sbd;
- spin_lock(&sdp->sd_reclaim_lock);
- if (list_empty(&gl->gl_reclaim)) {
- gfs2_glock_hold(gl);
- list_add(&gl->gl_reclaim, &sdp->sd_reclaim_list);
- atomic_inc(&sdp->sd_reclaim_count);
- spin_unlock(&sdp->sd_reclaim_lock);
- wake_up(&sdp->sd_reclaim_wq);
- } else
- spin_unlock(&sdp->sd_reclaim_lock);
+ if (gl->gl_state == LM_ST_UNLOCKED)
+ return 0;
+ if (!list_empty(&gl->gl_holders))
+ return 0;
+ if (glops->go_demote_ok)
+ return glops->go_demote_ok(gl);
+ return 1;
}
-/**
- * gfs2_reclaim_glock - process the next glock on the filesystem's reclaim list
- * @sdp: the filesystem
- *
- * Called from gfs2_glockd() glock reclaim daemon, or when promoting a
- * different glock and we notice that there are a lot of glocks in the
- * reclaim list.
- *
- */
-void gfs2_reclaim_glock(struct gfs2_sbd *sdp)
+static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask)
{
struct gfs2_glock *gl;
- int done_callback = 0;
+ int may_demote;
+ int nr_skipped = 0;
+ int got_ref = 0;
+ LIST_HEAD(skipped);
- spin_lock(&sdp->sd_reclaim_lock);
- if (list_empty(&sdp->sd_reclaim_list)) {
- spin_unlock(&sdp->sd_reclaim_lock);
- return;
- }
- gl = list_entry(sdp->sd_reclaim_list.next,
- struct gfs2_glock, gl_reclaim);
- list_del_init(&gl->gl_reclaim);
- spin_unlock(&sdp->sd_reclaim_lock);
+ if (nr == 0)
+ goto out;
- atomic_dec(&sdp->sd_reclaim_count);
- atomic_inc(&sdp->sd_reclaimed);
+ if (!(gfp_mask & __GFP_FS))
+ return -1;
- spin_lock(&gl->gl_spin);
- if (find_first_holder(gl) == NULL &&
- gl->gl_state != LM_ST_UNLOCKED && demote_ok(gl)) {
- handle_callback(gl, LM_ST_UNLOCKED, 0, 0);
- done_callback = 1;
+ spin_lock(&lru_lock);
+ while(nr && !list_empty(&lru_list)) {
+ gl = list_entry(lru_list.next, struct gfs2_glock, gl_lru);
+ list_del_init(&gl->gl_lru);
+ atomic_dec(&lru_count);
+
+ /* Test for being demotable */
+ if (!test_and_set_bit(GLF_LOCK, &gl->gl_flags)) {
+ gfs2_glock_hold(gl);
+ got_ref = 1;
+ spin_unlock(&lru_lock);
+ spin_lock(&gl->gl_spin);
+ may_demote = demote_ok(gl);
+ spin_unlock(&gl->gl_spin);
+ clear_bit(GLF_LOCK, &gl->gl_flags);
+ if (may_demote) {
+ handle_callback(gl, LM_ST_UNLOCKED, 0);
+ nr--;
+ if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
+ gfs2_glock_put(gl);
+ }
+ spin_lock(&lru_lock);
+ if (may_demote)
+ continue;
+ }
+ if (list_empty(&gl->gl_lru) &&
+ (atomic_read(&gl->gl_ref) <= (2 + got_ref))) {
+ nr_skipped++;
+ list_add(&gl->gl_lru, &skipped);
+ }
+ if (got_ref) {
+ spin_unlock(&lru_lock);
+ gfs2_glock_put(gl);
+ spin_lock(&lru_lock);
+ got_ref = 0;
+ }
}
- spin_unlock(&gl->gl_spin);
- if (!done_callback ||
- queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
- gfs2_glock_put(gl);
+ list_splice(&skipped, &lru_list);
+ atomic_add(nr_skipped, &lru_count);
+ spin_unlock(&lru_lock);
+out:
+ return (atomic_read(&lru_count) / 100) * sysctl_vfs_cache_pressure;
}
+static struct shrinker glock_shrinker = {
+ .shrink = gfs2_shrink_glock_memory,
+ .seeks = DEFAULT_SEEKS,
+};
+
/**
* examine_bucket - Call a function for glock in a hash bucket
* @examiner: the function
@@ -1457,26 +1516,6 @@ out:
}
/**
- * scan_glock - look at a glock and see if we can reclaim it
- * @gl: the glock to look at
- *
- */
-
-static void scan_glock(struct gfs2_glock *gl)
-{
- if (gl->gl_ops == &gfs2_inode_glops && gl->gl_object)
- return;
- if (test_bit(GLF_LOCK, &gl->gl_flags))
- return;
-
- spin_lock(&gl->gl_spin);
- if (find_first_holder(gl) == NULL &&
- gl->gl_state != LM_ST_UNLOCKED && demote_ok(gl))
- gfs2_glock_schedule_for_reclaim(gl);
- spin_unlock(&gl->gl_spin);
-}
-
-/**
* clear_glock - look at a glock and see if we can free it from glock cache
* @gl: the glock to look at
*
@@ -1484,23 +1523,16 @@ static void scan_glock(struct gfs2_glock *gl)
static void clear_glock(struct gfs2_glock *gl)
{
- struct gfs2_sbd *sdp = gl->gl_sbd;
- int released;
-
- spin_lock(&sdp->sd_reclaim_lock);
- if (!list_empty(&gl->gl_reclaim)) {
- list_del_init(&gl->gl_reclaim);
- atomic_dec(&sdp->sd_reclaim_count);
- spin_unlock(&sdp->sd_reclaim_lock);
- released = gfs2_glock_put(gl);
- gfs2_assert(sdp, !released);
- } else {
- spin_unlock(&sdp->sd_reclaim_lock);
+ spin_lock(&lru_lock);
+ if (!list_empty(&gl->gl_lru)) {
+ list_del_init(&gl->gl_lru);
+ atomic_dec(&lru_count);
}
+ spin_unlock(&lru_lock);
spin_lock(&gl->gl_spin);
if (find_first_holder(gl) == NULL && gl->gl_state != LM_ST_UNLOCKED)
- handle_callback(gl, LM_ST_UNLOCKED, 0, 0);
+ handle_callback(gl, LM_ST_UNLOCKED, 0);
spin_unlock(&gl->gl_spin);
gfs2_glock_hold(gl);
if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
@@ -1548,6 +1580,20 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp)
}
}
+void gfs2_glock_finish_truncate(struct gfs2_inode *ip)
+{
+ struct gfs2_glock *gl = ip->i_gl;
+ int ret;
+
+ ret = gfs2_truncatei_resume(ip);
+ gfs2_assert_withdraw(gl->gl_sbd, ret == 0);
+
+ spin_lock(&gl->gl_spin);
+ clear_bit(GLF_LOCK, &gl->gl_flags);
+ run_queue(gl, 1);
+ spin_unlock(&gl->gl_spin);
+}
+
static const char *state2str(unsigned state)
{
switch(state) {
@@ -1623,8 +1669,6 @@ static const char *gflags2str(char *buf, const unsigned long *gflags)
char *p = buf;
if (test_bit(GLF_LOCK, gflags))
*p++ = 'l';
- if (test_bit(GLF_STICKY, gflags))
- *p++ = 's';
if (test_bit(GLF_DEMOTE, gflags))
*p++ = 'D';
if (test_bit(GLF_PENDING_DEMOTE, gflags))
@@ -1743,34 +1787,6 @@ static int gfs2_dump_lockstate(struct gfs2_sbd *sdp)
return error;
}
-/**
- * gfs2_scand - Look for cached glocks and inodes to toss from memory
- * @sdp: Pointer to GFS2 superblock
- *
- * One of these daemons runs, finding candidates to add to sd_reclaim_list.
- * See gfs2_glockd()
- */
-
-static int gfs2_scand(void *data)
-{
- unsigned x;
- unsigned delay;
-
- while (!kthread_should_stop()) {
- for (x = 0; x < GFS2_GL_HASH_SIZE; x++)
- examine_bucket(scan_glock, NULL, x);
- if (freezing(current))
- refrigerator();
- delay = scand_secs;
- if (delay < 1)
- delay = 1;
- schedule_timeout_interruptible(delay * HZ);
- }
-
- return 0;
-}
-
-
int __init gfs2_glock_init(void)
{
@@ -1784,28 +1800,21 @@ int __init gfs2_glock_init(void)
}
#endif
- scand_process = kthread_run(gfs2_scand, NULL, "gfs2_scand");
- if (IS_ERR(scand_process))
- return PTR_ERR(scand_process);
-
glock_workqueue = create_workqueue("glock_workqueue");
- if (IS_ERR(glock_workqueue)) {
- kthread_stop(scand_process);
+ if (IS_ERR(glock_workqueue))
return PTR_ERR(glock_workqueue);
- }
+
+ register_shrinker(&glock_shrinker);
return 0;
}
void gfs2_glock_exit(void)
{
+ unregister_shrinker(&glock_shrinker);
destroy_workqueue(glock_workqueue);
- kthread_stop(scand_process);
}
-module_param(scand_secs, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(scand_secs, "The number of seconds between scand runs");
-
static int gfs2_glock_iter_next(struct gfs2_glock_iter *gi)
{
struct gfs2_glock *gl;
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
index 695c6b19361..543ec7ecfbd 100644
--- a/fs/gfs2/glock.h
+++ b/fs/gfs2/glock.h
@@ -129,9 +129,9 @@ int gfs2_lvb_hold(struct gfs2_glock *gl);
void gfs2_lvb_unhold(struct gfs2_glock *gl);
void gfs2_glock_cb(void *cb_data, unsigned int type, void *data);
-void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl);
void gfs2_reclaim_glock(struct gfs2_sbd *sdp);
void gfs2_gl_hash_clear(struct gfs2_sbd *sdp);
+void gfs2_glock_finish_truncate(struct gfs2_inode *ip);
int __init gfs2_glock_init(void);
void gfs2_glock_exit(void);
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index c6c318c2a0f..8522d3aa64f 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -201,19 +201,12 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
* Returns: 1 if it's ok
*/
-static int inode_go_demote_ok(struct gfs2_glock *gl)
+static int inode_go_demote_ok(const struct gfs2_glock *gl)
{
struct gfs2_sbd *sdp = gl->gl_sbd;
- int demote = 0;
-
- if (!gl->gl_object && !gl->gl_aspace->i_mapping->nrpages)
- demote = 1;
- else if (!sdp->sd_args.ar_localcaching &&
- time_after_eq(jiffies, gl->gl_stamp +
- gfs2_tune_get(sdp, gt_demote_secs) * HZ))
- demote = 1;
-
- return demote;
+ if (sdp->sd_jindex == gl->gl_object || sdp->sd_rindex == gl->gl_object)
+ return 0;
+ return 1;
}
/**
@@ -227,6 +220,7 @@ static int inode_go_demote_ok(struct gfs2_glock *gl)
static int inode_go_lock(struct gfs2_holder *gh)
{
struct gfs2_glock *gl = gh->gh_gl;
+ struct gfs2_sbd *sdp = gl->gl_sbd;
struct gfs2_inode *ip = gl->gl_object;
int error = 0;
@@ -239,10 +233,16 @@ static int inode_go_lock(struct gfs2_holder *gh)
return error;
}
- if ((ip->i_di.di_flags & GFS2_DIF_TRUNC_IN_PROG) &&
+ if ((ip->i_diskflags & GFS2_DIF_TRUNC_IN_PROG) &&
(gl->gl_state == LM_ST_EXCLUSIVE) &&
- (gh->gh_state == LM_ST_EXCLUSIVE))
- error = gfs2_truncatei_resume(ip);
+ (gh->gh_state == LM_ST_EXCLUSIVE)) {
+ spin_lock(&sdp->sd_trunc_lock);
+ if (list_empty(&ip->i_trunc_list))
+ list_add(&sdp->sd_trunc_list, &ip->i_trunc_list);
+ spin_unlock(&sdp->sd_trunc_lock);
+ wake_up(&sdp->sd_quota_wait);
+ return 1;
+ }
return error;
}
@@ -260,10 +260,13 @@ static int inode_go_dump(struct seq_file *seq, const struct gfs2_glock *gl)
const struct gfs2_inode *ip = gl->gl_object;
if (ip == NULL)
return 0;
- gfs2_print_dbg(seq, " I: n:%llu/%llu t:%u f:0x%08lx\n",
+ gfs2_print_dbg(seq, " I: n:%llu/%llu t:%u f:0x%02lx d:0x%08x s:%llu/%llu\n",
(unsigned long long)ip->i_no_formal_ino,
(unsigned long long)ip->i_no_addr,
- IF2DT(ip->i_inode.i_mode), ip->i_flags);
+ IF2DT(ip->i_inode.i_mode), ip->i_flags,
+ (unsigned int)ip->i_diskflags,
+ (unsigned long long)ip->i_inode.i_size,
+ (unsigned long long)ip->i_disksize);
return 0;
}
@@ -274,7 +277,7 @@ static int inode_go_dump(struct seq_file *seq, const struct gfs2_glock *gl)
* Returns: 1 if it's ok
*/
-static int rgrp_go_demote_ok(struct gfs2_glock *gl)
+static int rgrp_go_demote_ok(const struct gfs2_glock *gl)
{
return !gl->gl_aspace->i_mapping->nrpages;
}
@@ -318,7 +321,9 @@ static int rgrp_go_dump(struct seq_file *seq, const struct gfs2_glock *gl)
const struct gfs2_rgrpd *rgd = gl->gl_object;
if (rgd == NULL)
return 0;
- gfs2_print_dbg(seq, " R: n:%llu\n", (unsigned long long)rgd->rd_addr);
+ gfs2_print_dbg(seq, " R: n:%llu f:%02x b:%u/%u i:%u\n",
+ (unsigned long long)rgd->rd_addr, rgd->rd_flags,
+ rgd->rd_free, rgd->rd_free_clone, rgd->rd_dinodes);
return 0;
}
@@ -374,13 +379,25 @@ static int trans_go_xmote_bh(struct gfs2_glock *gl, struct gfs2_holder *gh)
}
/**
+ * trans_go_demote_ok
+ * @gl: the glock
+ *
+ * Always returns 0
+ */
+
+static int trans_go_demote_ok(const struct gfs2_glock *gl)
+{
+ return 0;
+}
+
+/**
* quota_go_demote_ok - Check to see if it's ok to unlock a quota glock
* @gl: the glock
*
* Returns: 1 if it's ok
*/
-static int quota_go_demote_ok(struct gfs2_glock *gl)
+static int quota_go_demote_ok(const struct gfs2_glock *gl)
{
return !atomic_read(&gl->gl_lvb_count);
}
@@ -414,6 +431,7 @@ const struct gfs2_glock_operations gfs2_rgrp_glops = {
const struct gfs2_glock_operations gfs2_trans_glops = {
.go_xmote_th = trans_go_sync,
.go_xmote_bh = trans_go_xmote_bh,
+ .go_demote_ok = trans_go_demote_ok,
.go_type = LM_TYPE_NONDISK,
};
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index f566ec1b4e8..608849d0002 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -68,12 +68,6 @@ struct gfs2_bitmap {
u32 bi_len;
};
-struct gfs2_rgrp_host {
- u32 rg_free;
- u32 rg_dinodes;
- u64 rg_igeneration;
-};
-
struct gfs2_rgrpd {
struct list_head rd_list; /* Link with superblock */
struct list_head rd_list_mru;
@@ -83,14 +77,16 @@ struct gfs2_rgrpd {
u32 rd_length; /* length of rgrp header in fs blocks */
u32 rd_data; /* num of data blocks in rgrp */
u32 rd_bitbytes; /* number of bytes in data bitmaps */
- struct gfs2_rgrp_host rd_rg;
+ u32 rd_free;
+ u32 rd_free_clone;
+ u32 rd_dinodes;
+ u64 rd_igeneration;
struct gfs2_bitmap *rd_bits;
- unsigned int rd_bh_count;
struct mutex rd_mutex;
- u32 rd_free_clone;
struct gfs2_log_element rd_le;
- u32 rd_last_alloc;
struct gfs2_sbd *rd_sbd;
+ unsigned int rd_bh_count;
+ u32 rd_last_alloc;
unsigned char rd_flags;
#define GFS2_RDF_CHECK 0x01 /* Need to check for unlinked inodes */
#define GFS2_RDF_NOALLOC 0x02 /* rg prohibits allocation */
@@ -129,7 +125,7 @@ struct gfs2_glock_operations {
void (*go_xmote_th) (struct gfs2_glock *gl);
int (*go_xmote_bh) (struct gfs2_glock *gl, struct gfs2_holder *gh);
void (*go_inval) (struct gfs2_glock *gl, int flags);
- int (*go_demote_ok) (struct gfs2_glock *gl);
+ int (*go_demote_ok) (const struct gfs2_glock *gl);
int (*go_lock) (struct gfs2_holder *gh);
void (*go_unlock) (struct gfs2_holder *gh);
int (*go_dump)(struct seq_file *seq, const struct gfs2_glock *gl);
@@ -159,7 +155,6 @@ struct gfs2_holder {
enum {
GLF_LOCK = 1,
- GLF_STICKY = 2,
GLF_DEMOTE = 3,
GLF_PENDING_DEMOTE = 4,
GLF_DEMOTE_IN_PROGRESS = 5,
@@ -194,7 +189,7 @@ struct gfs2_glock {
unsigned long gl_tchange;
void *gl_object;
- struct list_head gl_reclaim;
+ struct list_head gl_lru;
struct gfs2_sbd *gl_sbd;
@@ -233,29 +228,24 @@ enum {
GIF_USER = 4, /* user inode, not metadata addr space */
};
-struct gfs2_dinode_host {
- u64 di_size; /* number of bytes in file */
- u64 di_generation; /* generation number for NFS */
- u32 di_flags; /* GFS2_DIF_... */
- /* These only apply to directories */
- u32 di_entries; /* The number of entries in the directory */
- u64 di_eattr; /* extended attribute block number */
-};
struct gfs2_inode {
struct inode i_inode;
u64 i_no_addr;
u64 i_no_formal_ino;
+ u64 i_generation;
+ u64 i_eattr;
+ loff_t i_disksize;
unsigned long i_flags; /* GIF_... */
-
- struct gfs2_dinode_host i_di; /* To be replaced by ref to block */
-
struct gfs2_glock *i_gl; /* Move into i_gh? */
struct gfs2_holder i_iopen_gh;
struct gfs2_holder i_gh; /* for prepare/commit_write only */
struct gfs2_alloc *i_alloc;
u64 i_goal; /* goal block for allocations */
struct rw_semaphore i_rw_mutex;
+ struct list_head i_trunc_list;
+ u32 i_entries;
+ u32 i_diskflags;
u8 i_height;
u8 i_depth;
};
@@ -406,13 +396,11 @@ struct gfs2_args {
struct gfs2_tune {
spinlock_t gt_spin;
- unsigned int gt_demote_secs; /* Cache retention for unheld glock */
unsigned int gt_incore_log_blocks;
unsigned int gt_log_flush_secs;
unsigned int gt_recoverd_secs;
unsigned int gt_logd_secs;
- unsigned int gt_quotad_secs;
unsigned int gt_quota_simul_sync; /* Max quotavals to sync at once */
unsigned int gt_quota_warn_period; /* Secs between quota warn msgs */
@@ -488,10 +476,6 @@ struct gfs2_sbd {
/* Lock Stuff */
struct lm_lockstruct sd_lockstruct;
- struct list_head sd_reclaim_list;
- spinlock_t sd_reclaim_lock;
- wait_queue_head_t sd_reclaim_wq;
- atomic_t sd_reclaim_count;
struct gfs2_holder sd_live_gh;
struct gfs2_glock *sd_rename_gl;
struct gfs2_glock *sd_trans_gl;
@@ -519,7 +503,6 @@ struct gfs2_sbd {
spinlock_t sd_statfs_spin;
struct gfs2_statfs_change_host sd_statfs_master;
struct gfs2_statfs_change_host sd_statfs_local;
- unsigned long sd_statfs_sync_time;
/* Resource group stuff */
@@ -552,8 +535,6 @@ struct gfs2_sbd {
struct task_struct *sd_recoverd_process;
struct task_struct *sd_logd_process;
struct task_struct *sd_quotad_process;
- struct task_struct *sd_glockd_process[GFS2_GLOCKD_MAX];
- unsigned int sd_glockd_num;
/* Quota stuff */
@@ -561,13 +542,15 @@ struct gfs2_sbd {
atomic_t sd_quota_count;
spinlock_t sd_quota_spin;
struct mutex sd_quota_mutex;
+ wait_queue_head_t sd_quota_wait;
+ struct list_head sd_trunc_list;
+ spinlock_t sd_trunc_lock;
unsigned int sd_quota_slots;
unsigned int sd_quota_chunks;
unsigned char **sd_quota_bitmap;
u64 sd_quota_sync_gen;
- unsigned long sd_quota_sync_time;
/* Log stuff */
@@ -624,10 +607,6 @@ struct gfs2_sbd {
struct mutex sd_freeze_lock;
unsigned int sd_freeze_count;
- /* Counters */
-
- atomic_t sd_reclaimed;
-
char sd_fsname[GFS2_FSNAME_LEN];
char sd_table_name[GFS2_FSNAME_LEN];
char sd_proto_name[GFS2_FSNAME_LEN];
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index d57616840e8..3b87c188da4 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -32,7 +32,6 @@
#include "log.h"
#include "meta_io.h"
#include "ops_address.h"
-#include "ops_inode.h"
#include "quota.h"
#include "rgrp.h"
#include "trans.h"
@@ -248,7 +247,6 @@ fail:
static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
{
- struct gfs2_dinode_host *di = &ip->i_di;
const struct gfs2_dinode *str = buf;
struct timespec atime;
u16 height, depth;
@@ -274,8 +272,8 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
* to do that.
*/
ip->i_inode.i_nlink = be32_to_cpu(str->di_nlink);
- di->di_size = be64_to_cpu(str->di_size);
- i_size_write(&ip->i_inode, di->di_size);
+ ip->i_disksize = be64_to_cpu(str->di_size);
+ i_size_write(&ip->i_inode, ip->i_disksize);
gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks));
atime.tv_sec = be64_to_cpu(str->di_atime);
atime.tv_nsec = be32_to_cpu(str->di_atime_nsec);
@@ -287,9 +285,9 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
ip->i_inode.i_ctime.tv_nsec = be32_to_cpu(str->di_ctime_nsec);
ip->i_goal = be64_to_cpu(str->di_goal_meta);
- di->di_generation = be64_to_cpu(str->di_generation);
+ ip->i_generation = be64_to_cpu(str->di_generation);
- di->di_flags = be32_to_cpu(str->di_flags);
+ ip->i_diskflags = be32_to_cpu(str->di_flags);
gfs2_set_inode_flags(&ip->i_inode);
height = be16_to_cpu(str->di_height);
if (unlikely(height > GFS2_MAX_META_HEIGHT))
@@ -300,9 +298,9 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
if (unlikely(depth > GFS2_DIR_MAX_DEPTH))
goto corrupt;
ip->i_depth = (u8)depth;
- di->di_entries = be32_to_cpu(str->di_entries);
+ ip->i_entries = be32_to_cpu(str->di_entries);
- di->di_eattr = be64_to_cpu(str->di_eattr);
+ ip->i_eattr = be64_to_cpu(str->di_eattr);
if (S_ISREG(ip->i_inode.i_mode))
gfs2_set_aops(&ip->i_inode);
@@ -388,7 +386,6 @@ int gfs2_dinode_dealloc(struct gfs2_inode *ip)
gfs2_free_di(rgd, ip);
gfs2_trans_end(sdp);
- clear_bit(GLF_STICKY, &ip->i_gl->gl_flags);
out_rg_gunlock:
gfs2_glock_dq_uninit(&al->al_rgd_gh);
@@ -690,7 +687,7 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name,
return error;
}
- if (dip->i_di.di_entries == (u32)-1)
+ if (dip->i_entries == (u32)-1)
return -EFBIG;
if (S_ISDIR(mode) && dip->i_inode.i_nlink == (u32)-1)
return -EMLINK;
@@ -790,11 +787,11 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
di->di_flags = 0;
if (S_ISREG(mode)) {
- if ((dip->i_di.di_flags & GFS2_DIF_INHERIT_JDATA) ||
+ if ((dip->i_diskflags & GFS2_DIF_INHERIT_JDATA) ||
gfs2_tune_get(sdp, gt_new_files_jdata))
di->di_flags |= cpu_to_be32(GFS2_DIF_JDATA);
} else if (S_ISDIR(mode)) {
- di->di_flags |= cpu_to_be32(dip->i_di.di_flags &
+ di->di_flags |= cpu_to_be32(dip->i_diskflags &
GFS2_DIF_INHERIT_JDATA);
}
@@ -1068,7 +1065,7 @@ int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
struct qstr dotname;
int error;
- if (ip->i_di.di_entries != 2) {
+ if (ip->i_entries != 2) {
if (gfs2_consist_inode(ip))
gfs2_dinode_print(ip);
return -EIO;
@@ -1168,7 +1165,7 @@ int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len)
return error;
}
- if (!ip->i_di.di_size) {
+ if (!ip->i_disksize) {
gfs2_consist_inode(ip);
error = -EIO;
goto out;
@@ -1178,7 +1175,7 @@ int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len)
if (error)
goto out;
- x = ip->i_di.di_size + 1;
+ x = ip->i_disksize + 1;
if (x > *len) {
*buf = kmalloc(x, GFP_NOFS);
if (!*buf) {
@@ -1242,7 +1239,6 @@ int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr)
void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
{
- const struct gfs2_dinode_host *di = &ip->i_di;
struct gfs2_dinode *str = buf;
str->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
@@ -1256,7 +1252,7 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
str->di_uid = cpu_to_be32(ip->i_inode.i_uid);
str->di_gid = cpu_to_be32(ip->i_inode.i_gid);
str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink);
- str->di_size = cpu_to_be64(di->di_size);
+ str->di_size = cpu_to_be64(ip->i_disksize);
str->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode));
str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec);
@@ -1264,17 +1260,17 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
str->di_goal_meta = cpu_to_be64(ip->i_goal);
str->di_goal_data = cpu_to_be64(ip->i_goal);
- str->di_generation = cpu_to_be64(di->di_generation);
+ str->di_generation = cpu_to_be64(ip->i_generation);
- str->di_flags = cpu_to_be32(di->di_flags);
+ str->di_flags = cpu_to_be32(ip->i_diskflags);
str->di_height = cpu_to_be16(ip->i_height);
str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) &&
- !(ip->i_di.di_flags & GFS2_DIF_EXHASH) ?
+ !(ip->i_diskflags & GFS2_DIF_EXHASH) ?
GFS2_FORMAT_DE : 0);
str->di_depth = cpu_to_be16(ip->i_depth);
- str->di_entries = cpu_to_be32(di->di_entries);
+ str->di_entries = cpu_to_be32(ip->i_entries);
- str->di_eattr = cpu_to_be64(di->di_eattr);
+ str->di_eattr = cpu_to_be64(ip->i_eattr);
str->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec);
str->di_mtime_nsec = cpu_to_be32(ip->i_inode.i_mtime.tv_nsec);
str->di_ctime_nsec = cpu_to_be32(ip->i_inode.i_ctime.tv_nsec);
@@ -1282,22 +1278,21 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
void gfs2_dinode_print(const struct gfs2_inode *ip)
{
- const struct gfs2_dinode_host *di = &ip->i_di;
-
printk(KERN_INFO " no_formal_ino = %llu\n",
(unsigned long long)ip->i_no_formal_ino);
printk(KERN_INFO " no_addr = %llu\n",
(unsigned long long)ip->i_no_addr);
- printk(KERN_INFO " di_size = %llu\n", (unsigned long long)di->di_size);
+ printk(KERN_INFO " i_disksize = %llu\n",
+ (unsigned long long)ip->i_disksize);
printk(KERN_INFO " blocks = %llu\n",
(unsigned long long)gfs2_get_inode_blocks(&ip->i_inode));
printk(KERN_INFO " i_goal = %llu\n",
(unsigned long long)ip->i_goal);
- printk(KERN_INFO " di_flags = 0x%.8X\n", di->di_flags);
+ printk(KERN_INFO " i_diskflags = 0x%.8X\n", ip->i_diskflags);
printk(KERN_INFO " i_height = %u\n", ip->i_height);
printk(KERN_INFO " i_depth = %u\n", ip->i_depth);
- printk(KERN_INFO " di_entries = %u\n", di->di_entries);
- printk(KERN_INFO " di_eattr = %llu\n",
- (unsigned long long)di->di_eattr);
+ printk(KERN_INFO " i_entries = %u\n", ip->i_entries);
+ printk(KERN_INFO " i_eattr = %llu\n",
+ (unsigned long long)ip->i_eattr);
}
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h
index 2d43f69610a..d5329364cdf 100644
--- a/fs/gfs2/inode.h
+++ b/fs/gfs2/inode.h
@@ -10,6 +10,7 @@
#ifndef __INODE_DOT_H__
#define __INODE_DOT_H__
+#include <linux/fs.h>
#include "util.h"
static inline int gfs2_is_stuffed(const struct gfs2_inode *ip)
@@ -19,7 +20,7 @@ static inline int gfs2_is_stuffed(const struct gfs2_inode *ip)
static inline int gfs2_is_jdata(const struct gfs2_inode *ip)
{
- return ip->i_di.di_flags & GFS2_DIF_JDATA;
+ return ip->i_diskflags & GFS2_DIF_JDATA;
}
static inline int gfs2_is_writeback(const struct gfs2_inode *ip)
@@ -97,5 +98,15 @@ struct inode *gfs2_lookup_simple(struct inode *dip, const char *name);
void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf);
void gfs2_dinode_print(const struct gfs2_inode *ip);
+extern const struct inode_operations gfs2_file_iops;
+extern const struct inode_operations gfs2_dir_iops;
+extern const struct inode_operations gfs2_symlink_iops;
+extern const struct file_operations gfs2_file_fops;
+extern const struct file_operations gfs2_dir_fops;
+extern const struct file_operations gfs2_file_fops_nolock;
+extern const struct file_operations gfs2_dir_fops_nolock;
+
+extern void gfs2_set_inode_flags(struct inode *inode);
+
#endif /* __INODE_DOT_H__ */
diff --git a/fs/gfs2/locking/dlm/mount.c b/fs/gfs2/locking/dlm/mount.c
index 0c4cbe6c828..1aa7eb6a022 100644
--- a/fs/gfs2/locking/dlm/mount.c
+++ b/fs/gfs2/locking/dlm/mount.c
@@ -194,17 +194,25 @@ out:
static void gdlm_recovery_done(void *lockspace, unsigned int jid,
unsigned int message)
{
+ char env_jid[20];
+ char env_status[20];
+ char *envp[] = { env_jid, env_status, NULL };
struct gdlm_ls *ls = lockspace;
ls->recover_jid_done = jid;
ls->recover_jid_status = message;
- kobject_uevent(&ls->kobj, KOBJ_CHANGE);
+ sprintf(env_jid, "JID=%d", jid);
+ sprintf(env_status, "RECOVERY=%s",
+ message == LM_RD_SUCCESS ? "Done" : "Failed");
+ kobject_uevent_env(&ls->kobj, KOBJ_CHANGE, envp);
}
static void gdlm_others_may_mount(void *lockspace)
{
+ char *message = "FIRSTMOUNT=Done";
+ char *envp[] = { message, NULL };
struct gdlm_ls *ls = lockspace;
ls->first_done = 1;
- kobject_uevent(&ls->kobj, KOBJ_CHANGE);
+ kobject_uevent_env(&ls->kobj, KOBJ_CHANGE, envp);
}
/* Userspace gets the offline uevent, blocks new gfs locks on
diff --git a/fs/gfs2/locking/dlm/sysfs.c b/fs/gfs2/locking/dlm/sysfs.c
index 4ec571c3d8a..9b7edcf7bd4 100644
--- a/fs/gfs2/locking/dlm/sysfs.c
+++ b/fs/gfs2/locking/dlm/sysfs.c
@@ -195,9 +195,23 @@ void gdlm_kobject_release(struct gdlm_ls *ls)
kobject_put(&ls->kobj);
}
+static int gdlm_uevent(struct kset *kset, struct kobject *kobj,
+ struct kobj_uevent_env *env)
+{
+ struct gdlm_ls *ls = container_of(kobj, struct gdlm_ls, kobj);
+ add_uevent_var(env, "LOCKTABLE=%s:%s", ls->clustername, ls->fsname);
+ add_uevent_var(env, "LOCKPROTO=lock_dlm");
+ return 0;
+}
+
+static struct kset_uevent_ops gdlm_uevent_ops = {
+ .uevent = gdlm_uevent,
+};
+
+
int gdlm_sysfs_init(void)
{
- gdlm_kset = kset_create_and_add("lock_dlm", NULL, kernel_kobj);
+ gdlm_kset = kset_create_and_add("lock_dlm", &gdlm_uevent_ops, kernel_kobj);
if (!gdlm_kset) {
printk(KERN_WARNING "%s: can not create kset\n", __func__);
return -ENOMEM;
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c
index bb2cc303ac2..7cacfde3219 100644
--- a/fs/gfs2/main.c
+++ b/fs/gfs2/main.c
@@ -19,7 +19,7 @@
#include "gfs2.h"
#include "incore.h"
-#include "ops_fstype.h"
+#include "super.h"
#include "sys.h"
#include "util.h"
#include "glock.h"
@@ -30,6 +30,7 @@ static void gfs2_init_inode_once(void *foo)
inode_init_once(&ip->i_inode);
init_rwsem(&ip->i_rw_mutex);
+ INIT_LIST_HEAD(&ip->i_trunc_list);
ip->i_alloc = NULL;
}
@@ -42,7 +43,7 @@ static void gfs2_init_glock_once(void *foo)
INIT_LIST_HEAD(&gl->gl_holders);
gl->gl_lvb = NULL;
atomic_set(&gl->gl_lvb_count, 0);
- INIT_LIST_HEAD(&gl->gl_reclaim);
+ INIT_LIST_HEAD(&gl->gl_lru);
INIT_LIST_HEAD(&gl->gl_ail_list);
atomic_set(&gl->gl_ail_count, 0);
}
@@ -93,6 +94,12 @@ static int __init init_gfs2_fs(void)
if (!gfs2_rgrpd_cachep)
goto fail;
+ gfs2_quotad_cachep = kmem_cache_create("gfs2_quotad",
+ sizeof(struct gfs2_quota_data),
+ 0, 0, NULL);
+ if (!gfs2_quotad_cachep)
+ goto fail;
+
error = register_filesystem(&gfs2_fs_type);
if (error)
goto fail;
@@ -112,6 +119,9 @@ fail_unregister:
fail:
gfs2_glock_exit();
+ if (gfs2_quotad_cachep)
+ kmem_cache_destroy(gfs2_quotad_cachep);
+
if (gfs2_rgrpd_cachep)
kmem_cache_destroy(gfs2_rgrpd_cachep);
@@ -140,6 +150,7 @@ static void __exit exit_gfs2_fs(void)
unregister_filesystem(&gfs2_fs_type);
unregister_filesystem(&gfs2meta_fs_type);
+ kmem_cache_destroy(gfs2_quotad_cachep);
kmem_cache_destroy(gfs2_rgrpd_cachep);
kmem_cache_destroy(gfs2_bufdata_cachep);
kmem_cache_destroy(gfs2_inode_cachep);
diff --git a/fs/gfs2/mount.c b/fs/gfs2/mount.c
index f96eb90a2cf..3cb0a44ba02 100644
--- a/fs/gfs2/mount.c
+++ b/fs/gfs2/mount.c
@@ -32,7 +32,6 @@ enum {
Opt_debug,
Opt_nodebug,
Opt_upgrade,
- Opt_num_glockd,
Opt_acl,
Opt_noacl,
Opt_quota_off,
@@ -57,7 +56,6 @@ static const match_table_t tokens = {
{Opt_debug, "debug"},
{Opt_nodebug, "nodebug"},
{Opt_upgrade, "upgrade"},
- {Opt_num_glockd, "num_glockd=%d"},
{Opt_acl, "acl"},
{Opt_noacl, "noacl"},
{Opt_quota_off, "quota=off"},
@@ -87,16 +85,7 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount)
int error = 0;
if (!remount) {
- /* If someone preloaded options, use those instead */
- spin_lock(&gfs2_sys_margs_lock);
- if (gfs2_sys_margs) {
- data = gfs2_sys_margs;
- gfs2_sys_margs = NULL;
- }
- spin_unlock(&gfs2_sys_margs_lock);
-
/* Set some defaults */
- args->ar_num_glockd = GFS2_GLOCKD_DEFAULT;
args->ar_quota = GFS2_QUOTA_DEFAULT;
args->ar_data = GFS2_DATA_DEFAULT;
}
@@ -105,7 +94,7 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount)
process them */
for (options = data; (o = strsep(&options, ",")); ) {
- int token, option;
+ int token;
substring_t tmp[MAX_OPT_ARGS];
if (!*o)
@@ -196,22 +185,6 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount)
goto cant_remount;
args->ar_upgrade = 1;
break;
- case Opt_num_glockd:
- if ((error = match_int(&tmp[0], &option))) {
- fs_info(sdp, "problem getting num_glockd\n");
- goto out_error;
- }
-
- if (remount && option != args->ar_num_glockd)
- goto cant_remount;
- if (!option || option > GFS2_GLOCKD_MAX) {
- fs_info(sdp, "0 < num_glockd <= %u (not %u)\n",
- GFS2_GLOCKD_MAX, option);
- error = -EINVAL;
- goto out_error;
- }
- args->ar_num_glockd = option;
- break;
case Opt_acl:
args->ar_posix_acl = 1;
sdp->sd_vfs->s_flags |= MS_POSIXACL;
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 27563816e1c..6e4ea36c660 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -210,25 +210,23 @@ static int gfs2_jdata_writepage(struct page *page, struct writeback_control *wbc
{
struct inode *inode = page->mapping->host;
struct gfs2_sbd *sdp = GFS2_SB(inode);
- int error;
+ int ret;
int done_trans = 0;
- error = gfs2_writepage_common(page, wbc);
- if (error <= 0)
- return error;
-
if (PageChecked(page)) {
if (wbc->sync_mode != WB_SYNC_ALL)
goto out_ignore;
- error = gfs2_trans_begin(sdp, RES_DINODE + 1, 0);
- if (error)
+ ret = gfs2_trans_begin(sdp, RES_DINODE + 1, 0);
+ if (ret)
goto out_ignore;
done_trans = 1;
}
- error = __gfs2_jdata_writepage(page, wbc);
+ ret = gfs2_writepage_common(page, wbc);
+ if (ret > 0)
+ ret = __gfs2_jdata_writepage(page, wbc);
if (done_trans)
gfs2_trans_end(sdp);
- return error;
+ return ret;
out_ignore:
redirty_page_for_writepage(wbc, page);
@@ -453,8 +451,8 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
kaddr = kmap_atomic(page, KM_USER0);
memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode),
- ip->i_di.di_size);
- memset(kaddr + ip->i_di.di_size, 0, PAGE_CACHE_SIZE - ip->i_di.di_size);
+ ip->i_disksize);
+ memset(kaddr + ip->i_disksize, 0, PAGE_CACHE_SIZE - ip->i_disksize);
kunmap_atomic(kaddr, KM_USER0);
flush_dcache_page(page);
brelse(dibh);
@@ -627,7 +625,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
{
struct gfs2_inode *ip = GFS2_I(mapping->host);
struct gfs2_sbd *sdp = GFS2_SB(mapping->host);
- unsigned int data_blocks, ind_blocks, rblocks;
+ unsigned int data_blocks = 0, ind_blocks = 0, rblocks;
int alloc_required;
int error = 0;
struct gfs2_alloc *al;
@@ -641,11 +639,13 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
if (unlikely(error))
goto out_uninit;
- gfs2_write_calc_reserv(ip, len, &data_blocks, &ind_blocks);
error = gfs2_write_alloc_required(ip, pos, len, &alloc_required);
if (error)
goto out_unlock;
+ if (alloc_required || gfs2_is_jdata(ip))
+ gfs2_write_calc_reserv(ip, len, &data_blocks, &ind_blocks);
+
if (alloc_required) {
al = gfs2_alloc_get(ip);
if (!al) {
@@ -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;
@@ -782,7 +782,7 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh,
if (inode->i_size < to) {
i_size_write(inode, to);
- ip->i_di.di_size = inode->i_size;
+ ip->i_disksize = inode->i_size;
di->di_size = cpu_to_be64(inode->i_size);
mark_inode_dirty(inode);
}
@@ -847,9 +847,9 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
- if (likely(ret >= 0) && (inode->i_size > ip->i_di.di_size)) {
+ if (likely(ret >= 0) && (inode->i_size > ip->i_disksize)) {
di = (struct gfs2_dinode *)dibh->b_data;
- ip->i_di.di_size = inode->i_size;
+ ip->i_disksize = inode->i_size;
di->di_size = cpu_to_be64(inode->i_size);
mark_inode_dirty(inode);
}
diff --git a/fs/gfs2/ops_dentry.c b/fs/gfs2/ops_dentry.c
index 4a5e676b442..c2ad36330ca 100644
--- a/fs/gfs2/ops_dentry.c
+++ b/fs/gfs2/ops_dentry.c
@@ -19,7 +19,7 @@
#include "incore.h"
#include "dir.h"
#include "glock.h"
-#include "ops_dentry.h"
+#include "super.h"
#include "util.h"
#include "inode.h"
diff --git a/fs/gfs2/ops_dentry.h b/fs/gfs2/ops_dentry.h
deleted file mode 100644
index 5caa3db4d3f..00000000000
--- a/fs/gfs2/ops_dentry.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU General Public License version 2.
- */
-
-#ifndef __OPS_DENTRY_DOT_H__
-#define __OPS_DENTRY_DOT_H__
-
-#include <linux/dcache.h>
-
-extern struct dentry_operations gfs2_dops;
-
-#endif /* __OPS_DENTRY_DOT_H__ */
diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c
index bbb8c36403a..7fdeb14ddd1 100644
--- a/fs/gfs2/ops_export.c
+++ b/fs/gfs2/ops_export.c
@@ -22,8 +22,7 @@
#include "glock.h"
#include "glops.h"
#include "inode.h"
-#include "ops_dentry.h"
-#include "ops_fstype.h"
+#include "super.h"
#include "rgrp.h"
#include "util.h"
@@ -214,7 +213,7 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb,
}
error = -EIO;
- if (GFS2_I(inode)->i_di.di_flags & GFS2_DIF_SYSTEM) {
+ if (GFS2_I(inode)->i_diskflags & GFS2_DIF_SYSTEM) {
iput(inode);
goto fail;
}
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index 3a747f8e218..289c5f54ba5 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -39,7 +39,6 @@
#include "util.h"
#include "eaops.h"
#include "ops_address.h"
-#include "ops_inode.h"
/**
* gfs2_llseek - seek to a location in a file
@@ -158,8 +157,8 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
if (error)
return error;
- fsflags = fsflags_cvt(gfs2_to_fsflags, ip->i_di.di_flags);
- if (!S_ISDIR(inode->i_mode) && ip->i_di.di_flags & GFS2_DIF_JDATA)
+ fsflags = fsflags_cvt(gfs2_to_fsflags, ip->i_diskflags);
+ if (!S_ISDIR(inode->i_mode) && ip->i_diskflags & GFS2_DIF_JDATA)
fsflags |= FS_JOURNAL_DATA_FL;
if (put_user(fsflags, ptr))
error = -EFAULT;
@@ -172,17 +171,16 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
void gfs2_set_inode_flags(struct inode *inode)
{
struct gfs2_inode *ip = GFS2_I(inode);
- struct gfs2_dinode_host *di = &ip->i_di;
unsigned int flags = inode->i_flags;
flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
- if (di->di_flags & GFS2_DIF_IMMUTABLE)
+ if (ip->i_diskflags & GFS2_DIF_IMMUTABLE)
flags |= S_IMMUTABLE;
- if (di->di_flags & GFS2_DIF_APPENDONLY)
+ if (ip->i_diskflags & GFS2_DIF_APPENDONLY)
flags |= S_APPEND;
- if (di->di_flags & GFS2_DIF_NOATIME)
+ if (ip->i_diskflags & GFS2_DIF_NOATIME)
flags |= S_NOATIME;
- if (di->di_flags & GFS2_DIF_SYNC)
+ if (ip->i_diskflags & GFS2_DIF_SYNC)
flags |= S_SYNC;
inode->i_flags = flags;
}
@@ -221,7 +219,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
if (error)
goto out_drop_write;
- flags = ip->i_di.di_flags;
+ flags = ip->i_diskflags;
new_flags = (flags & ~mask) | (reqflags & mask);
if ((new_flags ^ flags) == 0)
goto out;
@@ -260,7 +258,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
if (error)
goto out_trans_end;
gfs2_trans_add_bh(ip->i_gl, bh, 1);
- ip->i_di.di_flags = new_flags;
+ ip->i_diskflags = new_flags;
gfs2_dinode_out(ip, bh->b_data);
brelse(bh);
gfs2_set_inode_flags(inode);
@@ -357,7 +355,6 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page)
goto out;
set_bit(GIF_SW_PAGED, &ip->i_flags);
- gfs2_write_calc_reserv(ip, PAGE_CACHE_SIZE, &data_blocks, &ind_blocks);
ret = gfs2_write_alloc_required(ip, pos, PAGE_CACHE_SIZE, &alloc_required);
if (ret || !alloc_required)
goto out_unlock;
@@ -369,6 +366,7 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page)
ret = gfs2_quota_lock_check(ip);
if (ret)
goto out_alloc_put;
+ gfs2_write_calc_reserv(ip, PAGE_CACHE_SIZE, &data_blocks, &ind_blocks);
al->al_requested = data_blocks + ind_blocks;
ret = gfs2_inplace_reserve(ip);
if (ret)
@@ -479,7 +477,7 @@ static int gfs2_open(struct inode *inode, struct file *file)
goto fail;
if (!(file->f_flags & O_LARGEFILE) &&
- ip->i_di.di_size > MAX_NON_LFS) {
+ ip->i_disksize > MAX_NON_LFS) {
error = -EOVERFLOW;
goto fail_gunlock;
}
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index b117fcf2c4f..f91eebdde58 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -22,20 +22,18 @@
#include "gfs2.h"
#include "incore.h"
#include "bmap.h"
-#include "daemon.h"
#include "glock.h"
#include "glops.h"
#include "inode.h"
#include "mount.h"
-#include "ops_fstype.h"
-#include "ops_dentry.h"
-#include "ops_super.h"
#include "recovery.h"
#include "rgrp.h"
#include "super.h"
#include "sys.h"
#include "util.h"
#include "log.h"
+#include "quota.h"
+#include "dir.h"
#define DO 0
#define UNDO 1
@@ -58,12 +56,10 @@ static void gfs2_tune_init(struct gfs2_tune *gt)
{
spin_lock_init(&gt->gt_spin);
- gt->gt_demote_secs = 300;
gt->gt_incore_log_blocks = 1024;
gt->gt_log_flush_secs = 60;
gt->gt_recoverd_secs = 60;
gt->gt_logd_secs = 1;
- gt->gt_quotad_secs = 5;
gt->gt_quota_simul_sync = 64;
gt->gt_quota_warn_period = 10;
gt->gt_quota_scale_num = 1;
@@ -91,10 +87,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
gfs2_tune_init(&sdp->sd_tune);
- INIT_LIST_HEAD(&sdp->sd_reclaim_list);
- spin_lock_init(&sdp->sd_reclaim_lock);
- init_waitqueue_head(&sdp->sd_reclaim_wq);
-
mutex_init(&sdp->sd_inum_mutex);
spin_lock_init(&sdp->sd_statfs_spin);
@@ -110,6 +102,9 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
INIT_LIST_HEAD(&sdp->sd_quota_list);
spin_lock_init(&sdp->sd_quota_spin);
mutex_init(&sdp->sd_quota_mutex);
+ init_waitqueue_head(&sdp->sd_quota_wait);
+ INIT_LIST_HEAD(&sdp->sd_trunc_list);
+ spin_lock_init(&sdp->sd_trunc_lock);
spin_lock_init(&sdp->sd_log_lock);
@@ -443,24 +438,11 @@ out:
static int init_locking(struct gfs2_sbd *sdp, struct gfs2_holder *mount_gh,
int undo)
{
- struct task_struct *p;
int error = 0;
if (undo)
goto fail_trans;
- for (sdp->sd_glockd_num = 0;
- sdp->sd_glockd_num < sdp->sd_args.ar_num_glockd;
- sdp->sd_glockd_num++) {
- p = kthread_run(gfs2_glockd, sdp, "gfs2_glockd");
- error = IS_ERR(p);
- if (error) {
- fs_err(sdp, "can't start glockd thread: %d\n", error);
- goto fail;
- }
- sdp->sd_glockd_process[sdp->sd_glockd_num] = p;
- }
-
error = gfs2_glock_nq_num(sdp,
GFS2_MOUNT_LOCK, &gfs2_nondisk_glops,
LM_ST_EXCLUSIVE, LM_FLAG_NOEXP | GL_NOCACHE,
@@ -493,7 +475,6 @@ static int init_locking(struct gfs2_sbd *sdp, struct gfs2_holder *mount_gh,
fs_err(sdp, "can't create transaction glock: %d\n", error);
goto fail_rename;
}
- set_bit(GLF_STICKY, &sdp->sd_trans_gl->gl_flags);
return 0;
@@ -506,9 +487,6 @@ fail_live:
fail_mount:
gfs2_glock_dq_uninit(mount_gh);
fail:
- while (sdp->sd_glockd_num--)
- kthread_stop(sdp->sd_glockd_process[sdp->sd_glockd_num]);
-
return error;
}
@@ -620,7 +598,7 @@ static int map_journal_extents(struct gfs2_sbd *sdp)
prev_db = 0;
- for (lb = 0; lb < ip->i_di.di_size >> sdp->sd_sb.sb_bsize_shift; lb++) {
+ for (lb = 0; lb < ip->i_disksize >> sdp->sd_sb.sb_bsize_shift; lb++) {
bh.b_state = 0;
bh.b_blocknr = 0;
bh.b_size = 1 << ip->i_inode.i_blkbits;
@@ -661,6 +639,72 @@ static void gfs2_lm_others_may_mount(struct gfs2_sbd *sdp)
sdp->sd_lockstruct.ls_lockspace);
}
+/**
+ * gfs2_jindex_hold - Grab a lock on the jindex
+ * @sdp: The GFS2 superblock
+ * @ji_gh: the holder for the jindex glock
+ *
+ * Returns: errno
+ */
+
+static int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh)
+{
+ struct gfs2_inode *dip = GFS2_I(sdp->sd_jindex);
+ struct qstr name;
+ char buf[20];
+ struct gfs2_jdesc *jd;
+ int error;
+
+ name.name = buf;
+
+ mutex_lock(&sdp->sd_jindex_mutex);
+
+ for (;;) {
+ error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, ji_gh);
+ if (error)
+ break;
+
+ name.len = sprintf(buf, "journal%u", sdp->sd_journals);
+ name.hash = gfs2_disk_hash(name.name, name.len);
+
+ error = gfs2_dir_check(sdp->sd_jindex, &name, NULL);
+ if (error == -ENOENT) {
+ error = 0;
+ break;
+ }
+
+ gfs2_glock_dq_uninit(ji_gh);
+
+ if (error)
+ break;
+
+ error = -ENOMEM;
+ jd = kzalloc(sizeof(struct gfs2_jdesc), GFP_KERNEL);
+ if (!jd)
+ break;
+
+ INIT_LIST_HEAD(&jd->extent_list);
+ jd->jd_inode = gfs2_lookupi(sdp->sd_jindex, &name, 1);
+ if (!jd->jd_inode || IS_ERR(jd->jd_inode)) {
+ if (!jd->jd_inode)
+ error = -ENOENT;
+ else
+ error = PTR_ERR(jd->jd_inode);
+ kfree(jd);
+ break;
+ }
+
+ spin_lock(&sdp->sd_jindex_spin);
+ jd->jd_jid = sdp->sd_journals++;
+ list_add_tail(&jd->jd_list, &sdp->sd_jindex_list);
+ spin_unlock(&sdp->sd_jindex_spin);
+ }
+
+ mutex_unlock(&sdp->sd_jindex_mutex);
+
+ return error;
+}
+
static int init_journal(struct gfs2_sbd *sdp, int undo)
{
struct inode *master = sdp->sd_master_dir->d_inode;
@@ -681,7 +725,6 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
return PTR_ERR(sdp->sd_jindex);
}
ip = GFS2_I(sdp->sd_jindex);
- set_bit(GLF_STICKY, &ip->i_gl->gl_flags);
/* Load in the journal index special file */
@@ -832,7 +875,6 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo)
goto fail_statfs;
}
ip = GFS2_I(sdp->sd_rindex);
- set_bit(GLF_STICKY, &ip->i_gl->gl_flags);
sdp->sd_rindex_uptodate = 0;
/* Read in the quota inode */
@@ -973,9 +1015,6 @@ static int init_threads(struct gfs2_sbd *sdp, int undo)
}
sdp->sd_logd_process = p;
- sdp->sd_statfs_sync_time = jiffies;
- sdp->sd_quota_sync_time = jiffies;
-
p = kthread_run(gfs2_quotad, sdp, "gfs2_quotad");
error = IS_ERR(p);
if (error) {
@@ -1224,17 +1263,21 @@ static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags,
static void gfs2_kill_sb(struct super_block *sb)
{
struct gfs2_sbd *sdp = sb->s_fs_info;
- if (sdp) {
- gfs2_meta_syncfs(sdp);
- dput(sdp->sd_root_dir);
- dput(sdp->sd_master_dir);
- sdp->sd_root_dir = NULL;
- sdp->sd_master_dir = NULL;
+
+ if (sdp == NULL) {
+ kill_block_super(sb);
+ return;
}
+
+ gfs2_meta_syncfs(sdp);
+ dput(sdp->sd_root_dir);
+ dput(sdp->sd_master_dir);
+ sdp->sd_root_dir = NULL;
+ sdp->sd_master_dir = NULL;
shrink_dcache_sb(sb);
kill_block_super(sb);
- if (sdp)
- gfs2_delete_debugfs_file(sdp);
+ gfs2_delete_debugfs_file(sdp);
+ kfree(sdp);
}
struct file_system_type gfs2_fs_type = {
diff --git a/fs/gfs2/ops_fstype.h b/fs/gfs2/ops_fstype.h
deleted file mode 100644
index da849051183..00000000000
--- a/fs/gfs2/ops_fstype.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU General Public License version 2.
- */
-
-#ifndef __OPS_FSTYPE_DOT_H__
-#define __OPS_FSTYPE_DOT_H__
-
-#include <linux/fs.h>
-
-extern struct file_system_type gfs2_fs_type;
-extern struct file_system_type gfs2meta_fs_type;
-extern const struct export_operations gfs2_export_ops;
-
-#endif /* __OPS_FSTYPE_DOT_H__ */
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index d232991b904..49877546beb 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -19,6 +19,7 @@
#include <linux/gfs2_ondisk.h>
#include <linux/crc32.h>
#include <linux/lm_interface.h>
+#include <linux/fiemap.h>
#include <asm/uaccess.h>
#include "gfs2.h"
@@ -31,12 +32,11 @@
#include "glock.h"
#include "inode.h"
#include "meta_io.h"
-#include "ops_dentry.h"
-#include "ops_inode.h"
#include "quota.h"
#include "rgrp.h"
#include "trans.h"
#include "util.h"
+#include "super.h"
/**
* gfs2_create - Create a file
@@ -185,7 +185,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
if (!dip->i_inode.i_nlink)
goto out_gunlock;
error = -EFBIG;
- if (dip->i_di.di_entries == (u32)-1)
+ if (dip->i_entries == (u32)-1)
goto out_gunlock;
error = -EPERM;
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
@@ -371,7 +371,7 @@ static int gfs2_symlink(struct inode *dir, struct dentry *dentry,
ip = ghs[1].gh_gl->gl_object;
- ip->i_di.di_size = size;
+ ip->i_disksize = size;
error = gfs2_meta_inode_buffer(ip, &dibh);
@@ -425,9 +425,9 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode)
ip = ghs[1].gh_gl->gl_object;
ip->i_inode.i_nlink = 2;
- ip->i_di.di_size = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode);
- ip->i_di.di_flags |= GFS2_DIF_JDATA;
- ip->i_di.di_entries = 2;
+ ip->i_disksize = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode);
+ ip->i_diskflags |= GFS2_DIF_JDATA;
+ ip->i_entries = 2;
error = gfs2_meta_inode_buffer(ip, &dibh);
@@ -517,13 +517,13 @@ static int gfs2_rmdir(struct inode *dir, struct dentry *dentry)
if (error)
goto out_gunlock;
- if (ip->i_di.di_entries < 2) {
+ if (ip->i_entries < 2) {
if (gfs2_consist_inode(ip))
gfs2_dinode_print(ip);
error = -EIO;
goto out_gunlock;
}
- if (ip->i_di.di_entries > 2) {
+ if (ip->i_entries > 2) {
error = -ENOTEMPTY;
goto out_gunlock;
}
@@ -726,13 +726,13 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
goto out_gunlock;
if (S_ISDIR(nip->i_inode.i_mode)) {
- if (nip->i_di.di_entries < 2) {
+ if (nip->i_entries < 2) {
if (gfs2_consist_inode(nip))
gfs2_dinode_print(nip);
error = -EIO;
goto out_gunlock;
}
- if (nip->i_di.di_entries > 2) {
+ if (nip->i_entries > 2) {
error = -ENOTEMPTY;
goto out_gunlock;
}
@@ -758,7 +758,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
error = -EINVAL;
goto out_gunlock;
}
- if (ndip->i_di.di_entries == (u32)-1) {
+ if (ndip->i_entries == (u32)-1) {
error = -EFBIG;
goto out_gunlock;
}
@@ -990,7 +990,7 @@ static int setattr_size(struct inode *inode, struct iattr *attr)
struct gfs2_sbd *sdp = GFS2_SB(inode);
int error;
- if (attr->ia_size != ip->i_di.di_size) {
+ if (attr->ia_size != ip->i_disksize) {
error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks);
if (error)
return error;
@@ -1001,8 +1001,8 @@ static int setattr_size(struct inode *inode, struct iattr *attr)
}
error = gfs2_truncatei(ip, attr->ia_size);
- if (error && (inode->i_size != ip->i_di.di_size))
- i_size_write(inode, ip->i_di.di_size);
+ if (error && (inode->i_size != ip->i_disksize))
+ i_size_write(inode, ip->i_disksize);
return error;
}
@@ -1212,6 +1212,48 @@ static int gfs2_removexattr(struct dentry *dentry, const char *name)
return gfs2_ea_remove(GFS2_I(dentry->d_inode), &er);
}
+static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ u64 start, u64 len)
+{
+ struct gfs2_inode *ip = GFS2_I(inode);
+ struct gfs2_holder gh;
+ int ret;
+
+ ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC);
+ if (ret)
+ return ret;
+
+ mutex_lock(&inode->i_mutex);
+
+ ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
+ if (ret)
+ goto out;
+
+ if (gfs2_is_stuffed(ip)) {
+ u64 phys = ip->i_no_addr << inode->i_blkbits;
+ u64 size = i_size_read(inode);
+ u32 flags = FIEMAP_EXTENT_LAST|FIEMAP_EXTENT_NOT_ALIGNED|
+ FIEMAP_EXTENT_DATA_INLINE;
+ phys += sizeof(struct gfs2_dinode);
+ phys += start;
+ if (start + len > size)
+ len = size - start;
+ if (start < size)
+ ret = fiemap_fill_next_extent(fieinfo, start, phys,
+ len, flags);
+ if (ret == 1)
+ ret = 0;
+ } else {
+ ret = __generic_block_fiemap(inode, fieinfo, start, len,
+ gfs2_block_map);
+ }
+
+ gfs2_glock_dq_uninit(&gh);
+out:
+ mutex_unlock(&inode->i_mutex);
+ return ret;
+}
+
const struct inode_operations gfs2_file_iops = {
.permission = gfs2_permission,
.setattr = gfs2_setattr,
@@ -1220,6 +1262,7 @@ const struct inode_operations gfs2_file_iops = {
.getxattr = gfs2_getxattr,
.listxattr = gfs2_listxattr,
.removexattr = gfs2_removexattr,
+ .fiemap = gfs2_fiemap,
};
const struct inode_operations gfs2_dir_iops = {
@@ -1239,6 +1282,7 @@ const struct inode_operations gfs2_dir_iops = {
.getxattr = gfs2_getxattr,
.listxattr = gfs2_listxattr,
.removexattr = gfs2_removexattr,
+ .fiemap = gfs2_fiemap,
};
const struct inode_operations gfs2_symlink_iops = {
@@ -1251,5 +1295,6 @@ const struct inode_operations gfs2_symlink_iops = {
.getxattr = gfs2_getxattr,
.listxattr = gfs2_listxattr,
.removexattr = gfs2_removexattr,
+ .fiemap = gfs2_fiemap,
};
diff --git a/fs/gfs2/ops_inode.h b/fs/gfs2/ops_inode.h
deleted file mode 100644
index 14b4b797622..00000000000
--- a/fs/gfs2/ops_inode.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU General Public License version 2.
- */
-
-#ifndef __OPS_INODE_DOT_H__
-#define __OPS_INODE_DOT_H__
-
-#include <linux/fs.h>
-
-extern const struct inode_operations gfs2_file_iops;
-extern const struct inode_operations gfs2_dir_iops;
-extern const struct inode_operations gfs2_symlink_iops;
-extern const struct file_operations gfs2_file_fops;
-extern const struct file_operations gfs2_dir_fops;
-extern const struct file_operations gfs2_file_fops_nolock;
-extern const struct file_operations gfs2_dir_fops_nolock;
-
-extern void gfs2_set_inode_flags(struct inode *inode);
-
-#endif /* __OPS_INODE_DOT_H__ */
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c
index d5355d9b592..777783deddc 100644
--- a/fs/gfs2/ops_super.c
+++ b/fs/gfs2/ops_super.c
@@ -28,7 +28,6 @@
#include "inode.h"
#include "log.h"
#include "mount.h"
-#include "ops_super.h"
#include "quota.h"
#include "recovery.h"
#include "rgrp.h"
@@ -143,8 +142,6 @@ static void gfs2_put_super(struct super_block *sb)
kthread_stop(sdp->sd_quotad_process);
kthread_stop(sdp->sd_logd_process);
kthread_stop(sdp->sd_recoverd_process);
- while (sdp->sd_glockd_num--)
- kthread_stop(sdp->sd_glockd_process[sdp->sd_glockd_num]);
if (!(sb->s_flags & MS_RDONLY)) {
error = gfs2_make_fs_ro(sdp);
@@ -185,7 +182,6 @@ static void gfs2_put_super(struct super_block *sb)
/* At this point, we're through participating in the lockspace */
gfs2_sys_fs_del(sdp);
- kfree(sdp);
}
/**
@@ -260,6 +256,137 @@ static void gfs2_unlockfs(struct super_block *sb)
}
/**
+ * statfs_fill - fill in the sg for a given RG
+ * @rgd: the RG
+ * @sc: the sc structure
+ *
+ * Returns: 0 on success, -ESTALE if the LVB is invalid
+ */
+
+static int statfs_slow_fill(struct gfs2_rgrpd *rgd,
+ struct gfs2_statfs_change_host *sc)
+{
+ gfs2_rgrp_verify(rgd);
+ sc->sc_total += rgd->rd_data;
+ sc->sc_free += rgd->rd_free;
+ sc->sc_dinodes += rgd->rd_dinodes;
+ return 0;
+}
+
+/**
+ * gfs2_statfs_slow - Stat a filesystem using asynchronous locking
+ * @sdp: the filesystem
+ * @sc: the sc info that will be returned
+ *
+ * Any error (other than a signal) will cause this routine to fall back
+ * to the synchronous version.
+ *
+ * FIXME: This really shouldn't busy wait like this.
+ *
+ * Returns: errno
+ */
+
+static int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc)
+{
+ struct gfs2_holder ri_gh;
+ struct gfs2_rgrpd *rgd_next;
+ struct gfs2_holder *gha, *gh;
+ unsigned int slots = 64;
+ unsigned int x;
+ int done;
+ int error = 0, err;
+
+ memset(sc, 0, sizeof(struct gfs2_statfs_change_host));
+ gha = kcalloc(slots, sizeof(struct gfs2_holder), GFP_KERNEL);
+ if (!gha)
+ return -ENOMEM;
+
+ error = gfs2_rindex_hold(sdp, &ri_gh);
+ if (error)
+ goto out;
+
+ rgd_next = gfs2_rgrpd_get_first(sdp);
+
+ for (;;) {
+ done = 1;
+
+ for (x = 0; x < slots; x++) {
+ gh = gha + x;
+
+ if (gh->gh_gl && gfs2_glock_poll(gh)) {
+ err = gfs2_glock_wait(gh);
+ if (err) {
+ gfs2_holder_uninit(gh);
+ error = err;
+ } else {
+ if (!error)
+ error = statfs_slow_fill(
+ gh->gh_gl->gl_object, sc);
+ gfs2_glock_dq_uninit(gh);
+ }
+ }
+
+ if (gh->gh_gl)
+ done = 0;
+ else if (rgd_next && !error) {
+ error = gfs2_glock_nq_init(rgd_next->rd_gl,
+ LM_ST_SHARED,
+ GL_ASYNC,
+ gh);
+ rgd_next = gfs2_rgrpd_get_next(rgd_next);
+ done = 0;
+ }
+
+ if (signal_pending(current))
+ error = -ERESTARTSYS;
+ }
+
+ if (done)
+ break;
+
+ yield();
+ }
+
+ gfs2_glock_dq_uninit(&ri_gh);
+
+out:
+ kfree(gha);
+ return error;
+}
+
+/**
+ * gfs2_statfs_i - Do a statfs
+ * @sdp: the filesystem
+ * @sg: the sg structure
+ *
+ * Returns: errno
+ */
+
+static int gfs2_statfs_i(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc)
+{
+ struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;
+ struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
+
+ spin_lock(&sdp->sd_statfs_spin);
+
+ *sc = *m_sc;
+ sc->sc_total += l_sc->sc_total;
+ sc->sc_free += l_sc->sc_free;
+ sc->sc_dinodes += l_sc->sc_dinodes;
+
+ spin_unlock(&sdp->sd_statfs_spin);
+
+ if (sc->sc_free < 0)
+ sc->sc_free = 0;
+ if (sc->sc_free > sc->sc_total)
+ sc->sc_free = sc->sc_total;
+ if (sc->sc_dinodes < 0)
+ sc->sc_dinodes = 0;
+
+ return 0;
+}
+
+/**
* gfs2_statfs - Gather and return stats about the filesystem
* @sb: The superblock
* @statfsbuf: The buffer
@@ -370,7 +497,6 @@ static void gfs2_clear_inode(struct inode *inode)
*/
if (test_bit(GIF_USER, &ip->i_flags)) {
ip->i_gl->gl_object = NULL;
- gfs2_glock_schedule_for_reclaim(ip->i_gl);
gfs2_glock_put(ip->i_gl);
ip->i_gl = NULL;
if (ip->i_iopen_gh.gh_gl) {
@@ -423,8 +549,6 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
seq_printf(s, ",debug");
if (args->ar_upgrade)
seq_printf(s, ",upgrade");
- if (args->ar_num_glockd != GFS2_GLOCKD_DEFAULT)
- seq_printf(s, ",num_glockd=%u", args->ar_num_glockd);
if (args->ar_posix_acl)
seq_printf(s, ",acl");
if (args->ar_quota != GFS2_QUOTA_DEFAULT) {
@@ -494,16 +618,16 @@ static void gfs2_delete_inode(struct inode *inode)
gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh);
error = gfs2_glock_nq(&ip->i_iopen_gh);
if (error)
- goto out_uninit;
+ goto out_truncate;
if (S_ISDIR(inode->i_mode) &&
- (ip->i_di.di_flags & GFS2_DIF_EXHASH)) {
+ (ip->i_diskflags & GFS2_DIF_EXHASH)) {
error = gfs2_dir_exhash_dealloc(ip);
if (error)
goto out_unlock;
}
- if (ip->i_di.di_eattr) {
+ if (ip->i_eattr) {
error = gfs2_ea_dealloc(ip);
if (error)
goto out_unlock;
@@ -519,6 +643,7 @@ static void gfs2_delete_inode(struct inode *inode)
if (error)
goto out_unlock;
+out_truncate:
error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks);
if (error)
goto out_unlock;
@@ -527,8 +652,8 @@ static void gfs2_delete_inode(struct inode *inode)
gfs2_trans_end(sdp);
out_unlock:
- gfs2_glock_dq(&ip->i_iopen_gh);
-out_uninit:
+ if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags))
+ gfs2_glock_dq(&ip->i_iopen_gh);
gfs2_holder_uninit(&ip->i_iopen_gh);
gfs2_glock_dq_uninit(&gh);
if (error && error != GLR_TRYFAILED)
diff --git a/fs/gfs2/ops_super.h b/fs/gfs2/ops_super.h
deleted file mode 100644
index 442a274c627..00000000000
--- a/fs/gfs2/ops_super.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU General Public License version 2.
- */
-
-#ifndef __OPS_SUPER_DOT_H__
-#define __OPS_SUPER_DOT_H__
-
-#include <linux/fs.h>
-
-extern const struct super_operations gfs2_super_ops;
-
-#endif /* __OPS_SUPER_DOT_H__ */
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 3e073f5144f..b08d09696b3 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -46,6 +46,8 @@
#include <linux/bio.h>
#include <linux/gfs2_ondisk.h>
#include <linux/lm_interface.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
#include "gfs2.h"
#include "incore.h"
@@ -94,7 +96,7 @@ static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id,
struct gfs2_quota_data *qd;
int error;
- qd = kzalloc(sizeof(struct gfs2_quota_data), GFP_NOFS);
+ qd = kmem_cache_zalloc(gfs2_quotad_cachep, GFP_NOFS);
if (!qd)
return -ENOMEM;
@@ -119,7 +121,7 @@ static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id,
return 0;
fail:
- kfree(qd);
+ kmem_cache_free(gfs2_quotad_cachep, qd);
return error;
}
@@ -158,7 +160,7 @@ static int qd_get(struct gfs2_sbd *sdp, int user, u32 id, int create,
if (qd || !create) {
if (new_qd) {
gfs2_lvb_unhold(new_qd->qd_gl);
- kfree(new_qd);
+ kmem_cache_free(gfs2_quotad_cachep, new_qd);
}
*qdp = qd;
return 0;
@@ -1013,7 +1015,7 @@ void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), change))
return;
- if (ip->i_di.di_flags & GFS2_DIF_SYSTEM)
+ if (ip->i_diskflags & GFS2_DIF_SYSTEM)
return;
for (x = 0; x < al->al_qd_num; x++) {
@@ -1100,15 +1102,15 @@ static void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *
int gfs2_quota_init(struct gfs2_sbd *sdp)
{
struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
- unsigned int blocks = ip->i_di.di_size >> sdp->sd_sb.sb_bsize_shift;
+ unsigned int blocks = ip->i_disksize >> sdp->sd_sb.sb_bsize_shift;
unsigned int x, slot = 0;
unsigned int found = 0;
u64 dblock;
u32 extlen = 0;
int error;
- if (!ip->i_di.di_size || ip->i_di.di_size > (64 << 20) ||
- ip->i_di.di_size & (sdp->sd_sb.sb_bsize - 1)) {
+ if (!ip->i_disksize || ip->i_disksize > (64 << 20) ||
+ ip->i_disksize & (sdp->sd_sb.sb_bsize - 1)) {
gfs2_consist_inode(ip);
return -EIO;
}
@@ -1195,7 +1197,7 @@ fail:
return error;
}
-void gfs2_quota_scan(struct gfs2_sbd *sdp)
+static void gfs2_quota_scan(struct gfs2_sbd *sdp)
{
struct gfs2_quota_data *qd, *safe;
LIST_HEAD(dead);
@@ -1222,7 +1224,7 @@ void gfs2_quota_scan(struct gfs2_sbd *sdp)
gfs2_assert_warn(sdp, !qd->qd_bh_count);
gfs2_lvb_unhold(qd->qd_gl);
- kfree(qd);
+ kmem_cache_free(gfs2_quotad_cachep, qd);
}
}
@@ -1257,7 +1259,7 @@ void gfs2_quota_cleanup(struct gfs2_sbd *sdp)
gfs2_assert_warn(sdp, !qd->qd_bh_count);
gfs2_lvb_unhold(qd->qd_gl);
- kfree(qd);
+ kmem_cache_free(gfs2_quotad_cachep, qd);
spin_lock(&sdp->sd_quota_spin);
}
@@ -1272,3 +1274,94 @@ void gfs2_quota_cleanup(struct gfs2_sbd *sdp)
}
}
+static void quotad_error(struct gfs2_sbd *sdp, const char *msg, int error)
+{
+ if (error == 0 || error == -EROFS)
+ return;
+ if (!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))
+ fs_err(sdp, "gfs2_quotad: %s error %d\n", msg, error);
+}
+
+static void quotad_check_timeo(struct gfs2_sbd *sdp, const char *msg,
+ int (*fxn)(struct gfs2_sbd *sdp),
+ unsigned long t, unsigned long *timeo,
+ unsigned int *new_timeo)
+{
+ if (t >= *timeo) {
+ int error = fxn(sdp);
+ quotad_error(sdp, msg, error);
+ *timeo = gfs2_tune_get_i(&sdp->sd_tune, new_timeo) * HZ;
+ } else {
+ *timeo -= t;
+ }
+}
+
+static void quotad_check_trunc_list(struct gfs2_sbd *sdp)
+{
+ struct gfs2_inode *ip;
+
+ while(1) {
+ ip = NULL;
+ spin_lock(&sdp->sd_trunc_lock);
+ if (!list_empty(&sdp->sd_trunc_list)) {
+ ip = list_entry(sdp->sd_trunc_list.next,
+ struct gfs2_inode, i_trunc_list);
+ list_del_init(&ip->i_trunc_list);
+ }
+ spin_unlock(&sdp->sd_trunc_lock);
+ if (ip == NULL)
+ return;
+ gfs2_glock_finish_truncate(ip);
+ }
+}
+
+/**
+ * gfs2_quotad - Write cached quota changes into the quota file
+ * @sdp: Pointer to GFS2 superblock
+ *
+ */
+
+int gfs2_quotad(void *data)
+{
+ struct gfs2_sbd *sdp = data;
+ struct gfs2_tune *tune = &sdp->sd_tune;
+ unsigned long statfs_timeo = 0;
+ unsigned long quotad_timeo = 0;
+ unsigned long t = 0;
+ DEFINE_WAIT(wait);
+ int empty;
+
+ while (!kthread_should_stop()) {
+
+ /* Update the master statfs file */
+ quotad_check_timeo(sdp, "statfs", gfs2_statfs_sync, t,
+ &statfs_timeo, &tune->gt_statfs_quantum);
+
+ /* Update quota file */
+ quotad_check_timeo(sdp, "sync", gfs2_quota_sync, t,
+ &quotad_timeo, &tune->gt_quota_quantum);
+
+ /* FIXME: This should be turned into a shrinker */
+ gfs2_quota_scan(sdp);
+
+ /* Check for & recover partially truncated inodes */
+ quotad_check_trunc_list(sdp);
+
+ if (freezing(current))
+ refrigerator();
+ t = min(quotad_timeo, statfs_timeo);
+
+ prepare_to_wait(&sdp->sd_quota_wait, &wait, TASK_UNINTERRUPTIBLE);
+ spin_lock(&sdp->sd_trunc_lock);
+ empty = list_empty(&sdp->sd_trunc_list);
+ spin_unlock(&sdp->sd_trunc_lock);
+ if (empty)
+ t -= schedule_timeout(t);
+ else
+ t = 0;
+ finish_wait(&sdp->sd_quota_wait, &wait);
+ }
+
+ return 0;
+}
+
diff --git a/fs/gfs2/quota.h b/fs/gfs2/quota.h
index 3b7f4b0e5df..cec9032be97 100644
--- a/fs/gfs2/quota.h
+++ b/fs/gfs2/quota.h
@@ -15,22 +15,22 @@ struct gfs2_sbd;
#define NO_QUOTA_CHANGE ((u32)-1)
-int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid);
-void gfs2_quota_unhold(struct gfs2_inode *ip);
+extern int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid);
+extern void gfs2_quota_unhold(struct gfs2_inode *ip);
-int gfs2_quota_lock(struct gfs2_inode *ip, u32 uid, u32 gid);
-void gfs2_quota_unlock(struct gfs2_inode *ip);
+extern int gfs2_quota_lock(struct gfs2_inode *ip, u32 uid, u32 gid);
+extern void gfs2_quota_unlock(struct gfs2_inode *ip);
-int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid);
-void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
- u32 uid, u32 gid);
+extern int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid);
+extern void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
+ u32 uid, u32 gid);
-int gfs2_quota_sync(struct gfs2_sbd *sdp);
-int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id);
+extern int gfs2_quota_sync(struct gfs2_sbd *sdp);
+extern int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id);
-int gfs2_quota_init(struct gfs2_sbd *sdp);
-void gfs2_quota_scan(struct gfs2_sbd *sdp);
-void gfs2_quota_cleanup(struct gfs2_sbd *sdp);
+extern int gfs2_quota_init(struct gfs2_sbd *sdp);
+extern void gfs2_quota_cleanup(struct gfs2_sbd *sdp);
+extern int gfs2_quotad(void *data);
static inline int gfs2_quota_lock_check(struct gfs2_inode *ip)
{
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
index d5e91f4f6a0..efd09c3d2b2 100644
--- a/fs/gfs2/recovery.c
+++ b/fs/gfs2/recovery.c
@@ -14,6 +14,8 @@
#include <linux/gfs2_ondisk.h>
#include <linux/crc32.h>
#include <linux/lm_interface.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
#include "gfs2.h"
#include "incore.h"
@@ -583,13 +585,35 @@ fail:
return error;
}
+static struct gfs2_jdesc *gfs2_jdesc_find_dirty(struct gfs2_sbd *sdp)
+{
+ struct gfs2_jdesc *jd;
+ int found = 0;
+
+ spin_lock(&sdp->sd_jindex_spin);
+
+ list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) {
+ if (jd->jd_dirty) {
+ jd->jd_dirty = 0;
+ found = 1;
+ break;
+ }
+ }
+ spin_unlock(&sdp->sd_jindex_spin);
+
+ if (!found)
+ jd = NULL;
+
+ return jd;
+}
+
/**
* gfs2_check_journals - Recover any dirty journals
* @sdp: the filesystem
*
*/
-void gfs2_check_journals(struct gfs2_sbd *sdp)
+static void gfs2_check_journals(struct gfs2_sbd *sdp)
{
struct gfs2_jdesc *jd;
@@ -603,3 +627,25 @@ void gfs2_check_journals(struct gfs2_sbd *sdp)
}
}
+/**
+ * gfs2_recoverd - Recover dead machine's journals
+ * @sdp: Pointer to GFS2 superblock
+ *
+ */
+
+int gfs2_recoverd(void *data)
+{
+ struct gfs2_sbd *sdp = data;
+ unsigned long t;
+
+ while (!kthread_should_stop()) {
+ gfs2_check_journals(sdp);
+ t = gfs2_tune_get(sdp, gt_recoverd_secs) * HZ;
+ if (freezing(current))
+ refrigerator();
+ schedule_timeout_interruptible(t);
+ }
+
+ return 0;
+}
+
diff --git a/fs/gfs2/recovery.h b/fs/gfs2/recovery.h
index f7235e61c72..a8218ea15b5 100644
--- a/fs/gfs2/recovery.h
+++ b/fs/gfs2/recovery.h
@@ -18,17 +18,17 @@ static inline void gfs2_replay_incr_blk(struct gfs2_sbd *sdp, unsigned int *blk)
*blk = 0;
}
-int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk,
+extern int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk,
struct buffer_head **bh);
-int gfs2_revoke_add(struct gfs2_sbd *sdp, u64 blkno, unsigned int where);
-int gfs2_revoke_check(struct gfs2_sbd *sdp, u64 blkno, unsigned int where);
-void gfs2_revoke_clean(struct gfs2_sbd *sdp);
+extern int gfs2_revoke_add(struct gfs2_sbd *sdp, u64 blkno, unsigned int where);
+extern int gfs2_revoke_check(struct gfs2_sbd *sdp, u64 blkno, unsigned int where);
+extern void gfs2_revoke_clean(struct gfs2_sbd *sdp);
-int gfs2_find_jhead(struct gfs2_jdesc *jd,
+extern int gfs2_find_jhead(struct gfs2_jdesc *jd,
struct gfs2_log_header_host *head);
-int gfs2_recover_journal(struct gfs2_jdesc *gfs2_jd);
-void gfs2_check_journals(struct gfs2_sbd *sdp);
+extern int gfs2_recover_journal(struct gfs2_jdesc *gfs2_jd);
+extern int gfs2_recoverd(void *data);
#endif /* __RECOVERY_DOT_H__ */
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 2d90fb25350..8b01c635d92 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -269,16 +269,14 @@ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd)
bi->bi_len, x);
}
- if (count[0] != rgd->rd_rg.rg_free) {
+ if (count[0] != rgd->rd_free) {
if (gfs2_consist_rgrpd(rgd))
fs_err(sdp, "free data mismatch: %u != %u\n",
- count[0], rgd->rd_rg.rg_free);
+ count[0], rgd->rd_free);
return;
}
- tmp = rgd->rd_data -
- rgd->rd_rg.rg_free -
- rgd->rd_rg.rg_dinodes;
+ tmp = rgd->rd_data - rgd->rd_free - rgd->rd_dinodes;
if (count[1] + count[2] != tmp) {
if (gfs2_consist_rgrpd(rgd))
fs_err(sdp, "used data mismatch: %u != %u\n",
@@ -286,10 +284,10 @@ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd)
return;
}
- if (count[3] != rgd->rd_rg.rg_dinodes) {
+ if (count[3] != rgd->rd_dinodes) {
if (gfs2_consist_rgrpd(rgd))
fs_err(sdp, "used metadata mismatch: %u != %u\n",
- count[3], rgd->rd_rg.rg_dinodes);
+ count[3], rgd->rd_dinodes);
return;
}
@@ -501,7 +499,7 @@ u64 gfs2_ri_total(struct gfs2_sbd *sdp)
for (rgrps = 0;; rgrps++) {
loff_t pos = rgrps * sizeof(struct gfs2_rindex);
- if (pos + sizeof(struct gfs2_rindex) >= ip->i_di.di_size)
+ if (pos + sizeof(struct gfs2_rindex) >= ip->i_disksize)
break;
error = gfs2_internal_read(ip, &ra_state, buf, &pos,
sizeof(struct gfs2_rindex));
@@ -590,7 +588,7 @@ static int gfs2_ri_update(struct gfs2_inode *ip)
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct inode *inode = &ip->i_inode;
struct file_ra_state ra_state;
- u64 rgrp_count = ip->i_di.di_size;
+ u64 rgrp_count = ip->i_disksize;
int error;
if (do_div(rgrp_count, sizeof(struct gfs2_rindex))) {
@@ -634,7 +632,7 @@ static int gfs2_ri_update_special(struct gfs2_inode *ip)
for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) {
/* Ignore partials */
if ((sdp->sd_rgrps + 1) * sizeof(struct gfs2_rindex) >
- ip->i_di.di_size)
+ ip->i_disksize)
break;
error = read_rindex_entry(ip, &ra_state);
if (error) {
@@ -692,7 +690,6 @@ int gfs2_rindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ri_gh)
static void gfs2_rgrp_in(struct gfs2_rgrpd *rgd, const void *buf)
{
const struct gfs2_rgrp *str = buf;
- struct gfs2_rgrp_host *rg = &rgd->rd_rg;
u32 rg_flags;
rg_flags = be32_to_cpu(str->rg_flags);
@@ -700,24 +697,23 @@ static void gfs2_rgrp_in(struct gfs2_rgrpd *rgd, const void *buf)
rgd->rd_flags |= GFS2_RDF_NOALLOC;
else
rgd->rd_flags &= ~GFS2_RDF_NOALLOC;
- rg->rg_free = be32_to_cpu(str->rg_free);
- rg->rg_dinodes = be32_to_cpu(str->rg_dinodes);
- rg->rg_igeneration = be64_to_cpu(str->rg_igeneration);
+ rgd->rd_free = be32_to_cpu(str->rg_free);
+ rgd->rd_dinodes = be32_to_cpu(str->rg_dinodes);
+ rgd->rd_igeneration = be64_to_cpu(str->rg_igeneration);
}
static void gfs2_rgrp_out(struct gfs2_rgrpd *rgd, void *buf)
{
struct gfs2_rgrp *str = buf;
- struct gfs2_rgrp_host *rg = &rgd->rd_rg;
u32 rg_flags = 0;
if (rgd->rd_flags & GFS2_RDF_NOALLOC)
rg_flags |= GFS2_RGF_NOALLOC;
str->rg_flags = cpu_to_be32(rg_flags);
- str->rg_free = cpu_to_be32(rg->rg_free);
- str->rg_dinodes = cpu_to_be32(rg->rg_dinodes);
+ str->rg_free = cpu_to_be32(rgd->rd_free);
+ str->rg_dinodes = cpu_to_be32(rgd->rd_dinodes);
str->__pad = cpu_to_be32(0);
- str->rg_igeneration = cpu_to_be64(rg->rg_igeneration);
+ str->rg_igeneration = cpu_to_be64(rgd->rd_igeneration);
memset(&str->rg_reserved, 0, sizeof(str->rg_reserved));
}
@@ -776,7 +772,7 @@ int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd)
}
spin_lock(&sdp->sd_rindex_spin);
- rgd->rd_free_clone = rgd->rd_rg.rg_free;
+ rgd->rd_free_clone = rgd->rd_free;
rgd->rd_bh_count++;
spin_unlock(&sdp->sd_rindex_spin);
@@ -850,7 +846,7 @@ void gfs2_rgrp_repolish_clones(struct gfs2_rgrpd *rgd)
}
spin_lock(&sdp->sd_rindex_spin);
- rgd->rd_free_clone = rgd->rd_rg.rg_free;
+ rgd->rd_free_clone = rgd->rd_free;
spin_unlock(&sdp->sd_rindex_spin);
}
@@ -1403,8 +1399,8 @@ u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n)
block = rgd->rd_data0 + blk;
ip->i_goal = block;
- gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free >= *n);
- rgd->rd_rg.rg_free -= *n;
+ gfs2_assert_withdraw(sdp, rgd->rd_free >= *n);
+ rgd->rd_free -= *n;
gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
@@ -1445,10 +1441,10 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation)
block = rgd->rd_data0 + blk;
- gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free);
- rgd->rd_rg.rg_free--;
- rgd->rd_rg.rg_dinodes++;
- *generation = rgd->rd_rg.rg_igeneration++;
+ gfs2_assert_withdraw(sdp, rgd->rd_free);
+ rgd->rd_free--;
+ rgd->rd_dinodes++;
+ *generation = rgd->rd_igeneration++;
gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
@@ -1481,7 +1477,7 @@ void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
if (!rgd)
return;
- rgd->rd_rg.rg_free += blen;
+ rgd->rd_free += blen;
gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
@@ -1509,7 +1505,7 @@ void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen)
if (!rgd)
return;
- rgd->rd_rg.rg_free += blen;
+ rgd->rd_free += blen;
gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
@@ -1546,10 +1542,10 @@ static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno)
return;
gfs2_assert_withdraw(sdp, rgd == tmp_rgd);
- if (!rgd->rd_rg.rg_dinodes)
+ if (!rgd->rd_dinodes)
gfs2_consist_rgrpd(rgd);
- rgd->rd_rg.rg_dinodes--;
- rgd->rd_rg.rg_free++;
+ rgd->rd_dinodes--;
+ rgd->rd_free++;
gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index c3ba3d9d0aa..141b781f2fc 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -34,76 +34,6 @@
#include "util.h"
/**
- * gfs2_jindex_hold - Grab a lock on the jindex
- * @sdp: The GFS2 superblock
- * @ji_gh: the holder for the jindex glock
- *
- * This is very similar to the gfs2_rindex_hold() function, except that
- * in general we hold the jindex lock for longer periods of time and
- * we grab it far less frequently (in general) then the rgrp lock.
- *
- * Returns: errno
- */
-
-int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh)
-{
- struct gfs2_inode *dip = GFS2_I(sdp->sd_jindex);
- struct qstr name;
- char buf[20];
- struct gfs2_jdesc *jd;
- int error;
-
- name.name = buf;
-
- mutex_lock(&sdp->sd_jindex_mutex);
-
- for (;;) {
- error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, ji_gh);
- if (error)
- break;
-
- name.len = sprintf(buf, "journal%u", sdp->sd_journals);
- name.hash = gfs2_disk_hash(name.name, name.len);
-
- error = gfs2_dir_check(sdp->sd_jindex, &name, NULL);
- if (error == -ENOENT) {
- error = 0;
- break;
- }
-
- gfs2_glock_dq_uninit(ji_gh);
-
- if (error)
- break;
-
- error = -ENOMEM;
- jd = kzalloc(sizeof(struct gfs2_jdesc), GFP_KERNEL);
- if (!jd)
- break;
-
- INIT_LIST_HEAD(&jd->extent_list);
- jd->jd_inode = gfs2_lookupi(sdp->sd_jindex, &name, 1);
- if (!jd->jd_inode || IS_ERR(jd->jd_inode)) {
- if (!jd->jd_inode)
- error = -ENOENT;
- else
- error = PTR_ERR(jd->jd_inode);
- kfree(jd);
- break;
- }
-
- spin_lock(&sdp->sd_jindex_spin);
- jd->jd_jid = sdp->sd_journals++;
- list_add_tail(&jd->jd_list, &sdp->sd_jindex_list);
- spin_unlock(&sdp->sd_jindex_spin);
- }
-
- mutex_unlock(&sdp->sd_jindex_mutex);
-
- return error;
-}
-
-/**
* gfs2_jindex_free - Clear all the journal index information
* @sdp: The GFS2 superblock
*
@@ -166,39 +96,6 @@ struct gfs2_jdesc *gfs2_jdesc_find(struct gfs2_sbd *sdp, unsigned int jid)
return jd;
}
-void gfs2_jdesc_make_dirty(struct gfs2_sbd *sdp, unsigned int jid)
-{
- struct gfs2_jdesc *jd;
-
- spin_lock(&sdp->sd_jindex_spin);
- jd = jdesc_find_i(&sdp->sd_jindex_list, jid);
- if (jd)
- jd->jd_dirty = 1;
- spin_unlock(&sdp->sd_jindex_spin);
-}
-
-struct gfs2_jdesc *gfs2_jdesc_find_dirty(struct gfs2_sbd *sdp)
-{
- struct gfs2_jdesc *jd;
- int found = 0;
-
- spin_lock(&sdp->sd_jindex_spin);
-
- list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) {
- if (jd->jd_dirty) {
- jd->jd_dirty = 0;
- found = 1;
- break;
- }
- }
- spin_unlock(&sdp->sd_jindex_spin);
-
- if (!found)
- jd = NULL;
-
- return jd;
-}
-
int gfs2_jdesc_check(struct gfs2_jdesc *jd)
{
struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
@@ -206,14 +103,14 @@ int gfs2_jdesc_check(struct gfs2_jdesc *jd)
int ar;
int error;
- if (ip->i_di.di_size < (8 << 20) || ip->i_di.di_size > (1 << 30) ||
- (ip->i_di.di_size & (sdp->sd_sb.sb_bsize - 1))) {
+ if (ip->i_disksize < (8 << 20) || ip->i_disksize > (1 << 30) ||
+ (ip->i_disksize & (sdp->sd_sb.sb_bsize - 1))) {
gfs2_consist_inode(ip);
return -EIO;
}
- jd->jd_blocks = ip->i_di.di_size >> sdp->sd_sb.sb_bsize_shift;
+ jd->jd_blocks = ip->i_disksize >> sdp->sd_sb.sb_bsize_shift;
- error = gfs2_write_alloc_required(ip, 0, ip->i_di.di_size, &ar);
+ error = gfs2_write_alloc_required(ip, 0, ip->i_disksize, &ar);
if (!error && ar) {
gfs2_consist_inode(ip);
error = -EIO;
@@ -423,137 +320,6 @@ out:
return error;
}
-/**
- * gfs2_statfs_i - Do a statfs
- * @sdp: the filesystem
- * @sg: the sg structure
- *
- * Returns: errno
- */
-
-int gfs2_statfs_i(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc)
-{
- struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;
- struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
-
- spin_lock(&sdp->sd_statfs_spin);
-
- *sc = *m_sc;
- sc->sc_total += l_sc->sc_total;
- sc->sc_free += l_sc->sc_free;
- sc->sc_dinodes += l_sc->sc_dinodes;
-
- spin_unlock(&sdp->sd_statfs_spin);
-
- if (sc->sc_free < 0)
- sc->sc_free = 0;
- if (sc->sc_free > sc->sc_total)
- sc->sc_free = sc->sc_total;
- if (sc->sc_dinodes < 0)
- sc->sc_dinodes = 0;
-
- return 0;
-}
-
-/**
- * statfs_fill - fill in the sg for a given RG
- * @rgd: the RG
- * @sc: the sc structure
- *
- * Returns: 0 on success, -ESTALE if the LVB is invalid
- */
-
-static int statfs_slow_fill(struct gfs2_rgrpd *rgd,
- struct gfs2_statfs_change_host *sc)
-{
- gfs2_rgrp_verify(rgd);
- sc->sc_total += rgd->rd_data;
- sc->sc_free += rgd->rd_rg.rg_free;
- sc->sc_dinodes += rgd->rd_rg.rg_dinodes;
- return 0;
-}
-
-/**
- * gfs2_statfs_slow - Stat a filesystem using asynchronous locking
- * @sdp: the filesystem
- * @sc: the sc info that will be returned
- *
- * Any error (other than a signal) will cause this routine to fall back
- * to the synchronous version.
- *
- * FIXME: This really shouldn't busy wait like this.
- *
- * Returns: errno
- */
-
-int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc)
-{
- struct gfs2_holder ri_gh;
- struct gfs2_rgrpd *rgd_next;
- struct gfs2_holder *gha, *gh;
- unsigned int slots = 64;
- unsigned int x;
- int done;
- int error = 0, err;
-
- memset(sc, 0, sizeof(struct gfs2_statfs_change_host));
- gha = kcalloc(slots, sizeof(struct gfs2_holder), GFP_KERNEL);
- if (!gha)
- return -ENOMEM;
-
- error = gfs2_rindex_hold(sdp, &ri_gh);
- if (error)
- goto out;
-
- rgd_next = gfs2_rgrpd_get_first(sdp);
-
- for (;;) {
- done = 1;
-
- for (x = 0; x < slots; x++) {
- gh = gha + x;
-
- if (gh->gh_gl && gfs2_glock_poll(gh)) {
- err = gfs2_glock_wait(gh);
- if (err) {
- gfs2_holder_uninit(gh);
- error = err;
- } else {
- if (!error)
- error = statfs_slow_fill(
- gh->gh_gl->gl_object, sc);
- gfs2_glock_dq_uninit(gh);
- }
- }
-
- if (gh->gh_gl)
- done = 0;
- else if (rgd_next && !error) {
- error = gfs2_glock_nq_init(rgd_next->rd_gl,
- LM_ST_SHARED,
- GL_ASYNC,
- gh);
- rgd_next = gfs2_rgrpd_get_next(rgd_next);
- done = 0;
- }
-
- if (signal_pending(current))
- error = -ERESTARTSYS;
- }
-
- if (done)
- break;
-
- yield();
- }
-
- gfs2_glock_dq_uninit(&ri_gh);
-
-out:
- kfree(gha);
- return error;
-}
-
struct lfcc {
struct list_head list;
struct gfs2_holder gh;
@@ -580,10 +346,6 @@ static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp,
struct gfs2_log_header_host lh;
int error;
- error = gfs2_jindex_hold(sdp, &ji_gh);
- if (error)
- return error;
-
list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) {
lfcc = kmalloc(sizeof(struct lfcc), GFP_KERNEL);
if (!lfcc) {
diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h
index 50a4c9b1215..f6b8b00ad88 100644
--- a/fs/gfs2/super.h
+++ b/fs/gfs2/super.h
@@ -10,6 +10,8 @@
#ifndef __SUPER_DOT_H__
#define __SUPER_DOT_H__
+#include <linux/fs.h>
+#include <linux/dcache.h>
#include "incore.h"
void gfs2_lm_unmount(struct gfs2_sbd *sdp);
@@ -23,12 +25,9 @@ static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp)
return x;
}
-int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh);
void gfs2_jindex_free(struct gfs2_sbd *sdp);
struct gfs2_jdesc *gfs2_jdesc_find(struct gfs2_sbd *sdp, unsigned int jid);
-void gfs2_jdesc_make_dirty(struct gfs2_sbd *sdp, unsigned int jid);
-struct gfs2_jdesc *gfs2_jdesc_find_dirty(struct gfs2_sbd *sdp);
int gfs2_jdesc_check(struct gfs2_jdesc *jd);
int gfs2_lookup_in_master_dir(struct gfs2_sbd *sdp, char *filename,
@@ -40,11 +39,15 @@ int gfs2_statfs_init(struct gfs2_sbd *sdp);
void gfs2_statfs_change(struct gfs2_sbd *sdp,
s64 total, s64 free, s64 dinodes);
int gfs2_statfs_sync(struct gfs2_sbd *sdp);
-int gfs2_statfs_i(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc);
-int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc);
int gfs2_freeze_fs(struct gfs2_sbd *sdp);
void gfs2_unfreeze_fs(struct gfs2_sbd *sdp);
+extern struct file_system_type gfs2_fs_type;
+extern struct file_system_type gfs2meta_fs_type;
+extern const struct export_operations gfs2_export_ops;
+extern const struct super_operations gfs2_super_ops;
+extern struct dentry_operations gfs2_dops;
+
#endif /* __SUPER_DOT_H__ */
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c
index 7e1879f1a02..26c1fa777a9 100644
--- a/fs/gfs2/sys.c
+++ b/fs/gfs2/sys.c
@@ -26,9 +26,6 @@
#include "quota.h"
#include "util.h"
-char *gfs2_sys_margs;
-spinlock_t gfs2_sys_margs_lock;
-
static ssize_t id_show(struct gfs2_sbd *sdp, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%u:%u\n",
@@ -263,7 +260,6 @@ ARGS_ATTR(localcaching, "%d\n");
ARGS_ATTR(localflocks, "%d\n");
ARGS_ATTR(debug, "%d\n");
ARGS_ATTR(upgrade, "%d\n");
-ARGS_ATTR(num_glockd, "%u\n");
ARGS_ATTR(posix_acl, "%d\n");
ARGS_ATTR(quota, "%u\n");
ARGS_ATTR(suiddir, "%d\n");
@@ -279,7 +275,6 @@ static struct attribute *args_attrs[] = {
&args_attr_localflocks.attr,
&args_attr_debug.attr,
&args_attr_upgrade.attr,
- &args_attr_num_glockd.attr,
&args_attr_posix_acl.attr,
&args_attr_quota.attr,
&args_attr_suiddir.attr,
@@ -288,30 +283,6 @@ static struct attribute *args_attrs[] = {
};
/*
- * display counters from superblock
- */
-
-struct counters_attr {
- struct attribute attr;
- ssize_t (*show)(struct gfs2_sbd *, char *);
-};
-
-#define COUNTERS_ATTR(name, fmt) \
-static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf) \
-{ \
- return snprintf(buf, PAGE_SIZE, fmt, \
- (unsigned int)atomic_read(&sdp->sd_##name)); \
-} \
-static struct counters_attr counters_attr_##name = __ATTR_RO(name)
-
-COUNTERS_ATTR(reclaimed, "%u\n");
-
-static struct attribute *counters_attrs[] = {
- &counters_attr_reclaimed.attr,
- NULL,
-};
-
-/*
* get and set struct gfs2_tune fields
*/
@@ -393,7 +364,6 @@ static ssize_t name##_store(struct gfs2_sbd *sdp, const char *buf, size_t len)\
} \
TUNE_ATTR_2(name, name##_store)
-TUNE_ATTR(demote_secs, 0);
TUNE_ATTR(incore_log_blocks, 0);
TUNE_ATTR(log_flush_secs, 0);
TUNE_ATTR(quota_warn_period, 0);
@@ -408,11 +378,9 @@ TUNE_ATTR(stall_secs, 1);
TUNE_ATTR(statfs_quantum, 1);
TUNE_ATTR_DAEMON(recoverd_secs, recoverd_process);
TUNE_ATTR_DAEMON(logd_secs, logd_process);
-TUNE_ATTR_DAEMON(quotad_secs, quotad_process);
TUNE_ATTR_3(quota_scale, quota_scale_show, quota_scale_store);
static struct attribute *tune_attrs[] = {
- &tune_attr_demote_secs.attr,
&tune_attr_incore_log_blocks.attr,
&tune_attr_log_flush_secs.attr,
&tune_attr_quota_warn_period.attr,
@@ -426,7 +394,6 @@ static struct attribute *tune_attrs[] = {
&tune_attr_statfs_quantum.attr,
&tune_attr_recoverd_secs.attr,
&tune_attr_logd_secs.attr,
- &tune_attr_quotad_secs.attr,
&tune_attr_quota_scale.attr,
&tune_attr_new_files_jdata.attr,
NULL,
@@ -437,11 +404,6 @@ static struct attribute_group lockstruct_group = {
.attrs = lockstruct_attrs,
};
-static struct attribute_group counters_group = {
- .name = "counters",
- .attrs = counters_attrs,
-};
-
static struct attribute_group args_group = {
.name = "args",
.attrs = args_attrs,
@@ -466,13 +428,9 @@ int gfs2_sys_fs_add(struct gfs2_sbd *sdp)
if (error)
goto fail_reg;
- error = sysfs_create_group(&sdp->sd_kobj, &counters_group);
- if (error)
- goto fail_lockstruct;
-
error = sysfs_create_group(&sdp->sd_kobj, &args_group);
if (error)
- goto fail_counters;
+ goto fail_lockstruct;
error = sysfs_create_group(&sdp->sd_kobj, &tune_group);
if (error)
@@ -483,8 +441,6 @@ int gfs2_sys_fs_add(struct gfs2_sbd *sdp)
fail_args:
sysfs_remove_group(&sdp->sd_kobj, &args_group);
-fail_counters:
- sysfs_remove_group(&sdp->sd_kobj, &counters_group);
fail_lockstruct:
sysfs_remove_group(&sdp->sd_kobj, &lockstruct_group);
fail_reg:
@@ -498,16 +454,27 @@ void gfs2_sys_fs_del(struct gfs2_sbd *sdp)
{
sysfs_remove_group(&sdp->sd_kobj, &tune_group);
sysfs_remove_group(&sdp->sd_kobj, &args_group);
- sysfs_remove_group(&sdp->sd_kobj, &counters_group);
sysfs_remove_group(&sdp->sd_kobj, &lockstruct_group);
kobject_put(&sdp->sd_kobj);
}
+static int gfs2_uevent(struct kset *kset, struct kobject *kobj,
+ struct kobj_uevent_env *env)
+{
+ struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj);
+ add_uevent_var(env, "LOCKTABLE=%s", sdp->sd_table_name);
+ add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name);
+ return 0;
+}
+
+static struct kset_uevent_ops gfs2_uevent_ops = {
+ .uevent = gfs2_uevent,
+};
+
+
int gfs2_sys_init(void)
{
- gfs2_sys_margs = NULL;
- spin_lock_init(&gfs2_sys_margs_lock);
- gfs2_kset = kset_create_and_add("gfs2", NULL, fs_kobj);
+ gfs2_kset = kset_create_and_add("gfs2", &gfs2_uevent_ops, fs_kobj);
if (!gfs2_kset)
return -ENOMEM;
return 0;
@@ -515,7 +482,6 @@ int gfs2_sys_init(void)
void gfs2_sys_uninit(void)
{
- kfree(gfs2_sys_margs);
kset_unregister(gfs2_kset);
}
diff --git a/fs/gfs2/sys.h b/fs/gfs2/sys.h
index 1ca8cdac530..e94560e836d 100644
--- a/fs/gfs2/sys.h
+++ b/fs/gfs2/sys.h
@@ -13,10 +13,6 @@
#include <linux/spinlock.h>
struct gfs2_sbd;
-/* Allow args to be passed to GFS2 when using an initial ram disk */
-extern char *gfs2_sys_margs;
-extern spinlock_t gfs2_sys_margs_lock;
-
int gfs2_sys_fs_add(struct gfs2_sbd *sdp);
void gfs2_sys_fs_del(struct gfs2_sbd *sdp);
diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c
index d31e355c61f..374f50e9549 100644
--- a/fs/gfs2/util.c
+++ b/fs/gfs2/util.c
@@ -25,6 +25,7 @@ struct kmem_cache *gfs2_glock_cachep __read_mostly;
struct kmem_cache *gfs2_inode_cachep __read_mostly;
struct kmem_cache *gfs2_bufdata_cachep __read_mostly;
struct kmem_cache *gfs2_rgrpd_cachep __read_mostly;
+struct kmem_cache *gfs2_quotad_cachep __read_mostly;
void gfs2_assert_i(struct gfs2_sbd *sdp)
{
diff --git a/fs/gfs2/util.h b/fs/gfs2/util.h
index 7f48576289c..33e96b0ce9a 100644
--- a/fs/gfs2/util.h
+++ b/fs/gfs2/util.h
@@ -148,6 +148,7 @@ extern struct kmem_cache *gfs2_glock_cachep;
extern struct kmem_cache *gfs2_inode_cachep;
extern struct kmem_cache *gfs2_bufdata_cachep;
extern struct kmem_cache *gfs2_rgrpd_cachep;
+extern struct kmem_cache *gfs2_quotad_cachep;
static inline unsigned int gfs2_tune_get_i(struct gfs2_tune *gt,
unsigned int *p)
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 3a31451ac17..5c538e0ec14 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -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;
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 7d479ce3ace..0ab0c6f5f43 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -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;
diff --git a/fs/inode.c b/fs/inode.c
index 7de1cda9248..bd48e5e6d3e 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -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;
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 43e8b2c0664..cc3f1aa1cf7 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -231,7 +231,8 @@ static int ioctl_fiemap(struct file *filp, unsigned long arg)
#define blk_to_logical(inode, blk) (blk << (inode)->i_blkbits)
#define logical_to_blk(inode, offset) (offset >> (inode)->i_blkbits);
-/*
+/**
+ * __generic_block_fiemap - FIEMAP for block based inodes (no locking)
* @inode - the inode to map
* @arg - the pointer to userspace where we copy everything to
* @get_block - the fs's get_block function
@@ -242,11 +243,15 @@ static int ioctl_fiemap(struct file *filp, unsigned long arg)
*
* If it is possible to have data blocks beyond a hole past @inode->i_size, then
* please do not use this function, it will stop at the first unmapped block
- * beyond i_size
+ * beyond i_size.
+ *
+ * If you use this function directly, you need to do your own locking. Use
+ * generic_block_fiemap if you want the locking done for you.
*/
-int generic_block_fiemap(struct inode *inode,
- struct fiemap_extent_info *fieinfo, u64 start,
- u64 len, get_block_t *get_block)
+
+int __generic_block_fiemap(struct inode *inode,
+ struct fiemap_extent_info *fieinfo, u64 start,
+ u64 len, get_block_t *get_block)
{
struct buffer_head tmp;
unsigned int start_blk;
@@ -260,9 +265,6 @@ int generic_block_fiemap(struct inode *inode,
start_blk = logical_to_blk(inode, start);
- /* guard against change */
- mutex_lock(&inode->i_mutex);
-
length = (long long)min_t(u64, len, i_size_read(inode));
map_len = length;
@@ -334,14 +336,36 @@ int generic_block_fiemap(struct inode *inode,
cond_resched();
} while (1);
- mutex_unlock(&inode->i_mutex);
-
/* if ret is 1 then we just hit the end of the extent array */
if (ret == 1)
ret = 0;
return ret;
}
+EXPORT_SYMBOL(__generic_block_fiemap);
+
+/**
+ * generic_block_fiemap - FIEMAP for block based inodes
+ * @inode: The inode to map
+ * @fieinfo: The mapping information
+ * @start: The initial block to map
+ * @len: The length of the extect to attempt to map
+ * @get_block: The block mapping function for the fs
+ *
+ * Calls __generic_block_fiemap to map the inode, after taking
+ * the inode's mutex lock.
+ */
+
+int generic_block_fiemap(struct inode *inode,
+ struct fiemap_extent_info *fieinfo, u64 start,
+ u64 len, get_block_t *get_block)
+{
+ int ret;
+ mutex_lock(&inode->i_mutex);
+ ret = __generic_block_fiemap(inode, fieinfo, start, len, get_block);
+ mutex_unlock(&inode->i_mutex);
+ return ret;
+}
EXPORT_SYMBOL(generic_block_fiemap);
#endif /* CONFIG_BLOCK */
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 3f8af0f1505..6147ec3643a 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -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;
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index ebc667bc54a..c8a1bace685 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -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);
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index e70d657a19f..f6bff9d6f8d 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -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,13 +316,23 @@ 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
*/
if (*((__be32 *)(mapped_data + new_offset)) ==
@@ -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;
}
/*
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index 39b7805a599..4f925a4f3d0 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -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);
@@ -944,6 +950,47 @@ out:
}
/**
+ * 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.
* @bh: buffer to mark
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 5a98aa87c85..5edc2bf2058 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -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;
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index d6363d8309d..0f94381ca6d 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -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);
}
diff --git a/fs/libfs.c b/fs/libfs.c
index e960a832190..49b44099dab 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -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;
diff --git a/fs/namei.c b/fs/namei.c
index dd5c9f0bf82..f05bed24242 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -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 = {
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index d319b49f8f0..90f292b520d 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -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;
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index d1c5f787b36..44aa92aba89 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -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) {
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index 400f8064a54..81b8644b013 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -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;
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index e9da092e277..86bef156cf0 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -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
diff --git a/fs/ocfs2/Makefile b/fs/ocfs2/Makefile
index 589dcdfdfe3..01596079dd6 100644
--- a/fs/ocfs2/Makefile
+++ b/fs/ocfs2/Makefile
@@ -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
index 00000000000..12dfb44c22e
--- /dev/null
+++ b/fs/ocfs2/acl.c
@@ -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
index 00000000000..8f6389ed4da
--- /dev/null
+++ b/fs/ocfs2/acl.h
@@ -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 */
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 0cc2deb9394..54ff4c77aaa 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -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;
diff --git a/fs/ocfs2/alloc.h b/fs/ocfs2/alloc.h
index 70257c84cfb..cceff5c37f4 100644
--- a/fs/ocfs2/alloc.h
+++ b/fs/ocfs2/alloc.h
@@ -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);
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index c22543b3342..a067a6cffb0 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -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
index 00000000000..2a947c44e59
--- /dev/null
+++ b/fs/ocfs2/blockcheck.c
@@ -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
index 00000000000..70ec3feda32
--- /dev/null
+++ b/fs/ocfs2/blockcheck.h
@@ -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
diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c
index 3a178ec48d7..15c8e6deee2 100644
--- a/fs/ocfs2/buffer_head_io.c
+++ b/fs/ocfs2/buffer_head_io.c
@@ -39,6 +39,18 @@
#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
diff --git a/fs/ocfs2/buffer_head_io.h b/fs/ocfs2/buffer_head_io.h
index 75e1dcb1ade..c75d682dadd 100644
--- a/fs/ocfs2/buffer_head_io.h
+++ b/fs/ocfs2/buffer_head_io.h
@@ -31,21 +31,24 @@
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;
diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c
index d8a0cb92cef..96df5416993 100644
--- a/fs/ocfs2/cluster/masklog.c
+++ b/fs/ocfs2/cluster/masklog.c
@@ -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),
diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h
index 57670c68047..7e72a81bc2d 100644
--- a/fs/ocfs2/cluster/masklog.h
+++ b/fs/ocfs2/cluster/masklog.h
@@ -113,6 +113,7 @@
#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 */
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index 026e6eb8518..f2c4098cf33 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -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));
}
diff --git a/fs/ocfs2/dir.h b/fs/ocfs2/dir.h
index ce48b9080d8..c511e2e18e9 100644
--- a/fs/ocfs2/dir.h
+++ b/fs/ocfs2/dir.h
@@ -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 */
diff --git a/fs/ocfs2/dlm/dlmast.c b/fs/ocfs2/dlm/dlmast.c
index 644bee55d8b..d07ddbe4b28 100644
--- a/fs/ocfs2/dlm/dlmast.c
+++ b/fs/ocfs2/dlm/dlmast.c
@@ -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);
diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h
index d5a86fb81a4..bb53714813a 100644
--- a/fs/ocfs2/dlm/dlmcommon.h
+++ b/fs/ocfs2/dlm/dlmcommon.h
@@ -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;
diff --git a/fs/ocfs2/dlm/dlmdebug.c b/fs/ocfs2/dlm/dlmdebug.c
index 1b81dcba175..b32f60a5acf 100644
--- a/fs/ocfs2/dlm/dlmdebug.c
+++ b/fs/ocfs2/dlm/dlmdebug.c
@@ -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;
}
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
index 63f8125824e..d8d578f4561 100644
--- a/fs/ocfs2/dlm/dlmdomain.c
+++ b/fs/ocfs2/dlm/dlmdomain.c
@@ -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);
diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c
index 6f7a77d5402..1c9efb406a9 100644
--- a/fs/ocfs2/dlm/dlmfs.c
+++ b/fs/ocfs2/dlm/dlmfs.c
@@ -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;
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index 44f87caf368..54e182a27ca 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -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;
diff --git a/fs/ocfs2/dlm/dlmthread.c b/fs/ocfs2/dlm/dlmthread.c
index 4060bb328bc..d1295203029 100644
--- a/fs/ocfs2/dlm/dlmthread.c
+++ b/fs/ocfs2/dlm/dlmthread.c
@@ -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 */
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 6e6cc0a2e5f..f731ab49179 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -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.
diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h
index 2bb01f09c1b..3f8d9986b8e 100644
--- a/fs/ocfs2/dlmglue.h
+++ b/fs/ocfs2/dlmglue.h
@@ -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,
diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c
index 2baedac5823..f2bb1a04d25 100644
--- a/fs/ocfs2/extent_map.c
+++ b/fs/ocfs2/extent_map.c
@@ -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;
+}
+
+
diff --git a/fs/ocfs2/extent_map.h b/fs/ocfs2/extent_map.h
index 1c4aa8b06f3..b7dd9731b46 100644
--- a/fs/ocfs2/extent_map.h
+++ b/fs/ocfs2/extent_map.h
@@ -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 */
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index e2570a3bc2b..e8f795f978a 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -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;
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h
index e92382cbca5..172f9fbc9fc 100644
--- a/fs/ocfs2/file.h
+++ b/fs/ocfs2/file.h
@@ -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);
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index 7aa00d51187..229e707bc05 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -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);
+}
diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h
index 2f37af9bcc4..eb3c302b38d 100644
--- a/fs/ocfs2/inode.h
+++ b/fs/ocfs2/inode.h
@@ -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 */
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index 99fe9d584f3..57d7d25a2b9 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -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
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h
index d4d14e9a3ce..3c3532e1307 100644
--- a/fs/ocfs2/journal.h
+++ b/fs/ocfs2/journal.h
@@ -27,12 +27,7 @@
#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;
}
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c
index 687b28713c3..ec70cdbe77f 100644
--- a/fs/ocfs2/localalloc.c
+++ b/fs/ocfs2/localalloc.c
@@ -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;
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 2545e7402ef..084aba86c3b 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -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>
@@ -61,17 +62,18 @@
#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;
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index 3fed9e3d899..ad5c24a29ed 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -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 */
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
index 5e0c0d0aef7..c7ae45aaa36 100644
--- a/fs/ocfs2/ocfs2_fs.h
+++ b/fs/ocfs2/ocfs2_fs.h
@@ -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) \
@@ -93,8 +94,11 @@
| 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
@@ -147,6 +151,9 @@
/* 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.
@@ -163,6 +170,12 @@
*/
#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.
*/
@@ -192,6 +205,7 @@
#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 */
@@ -410,6 +432,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 */
@@ -715,6 +754,34 @@ struct ocfs2_dir_entry {
} __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
*/
struct ocfs2_group_desc
@@ -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
index b91c78f8f55..00000000000
--- a/fs/ocfs2/ocfs2_jbd_compat.h
+++ /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 */
diff --git a/fs/ocfs2/ocfs2_lockid.h b/fs/ocfs2/ocfs2_lockid.h
index 82c200f7a8f..eb6f50c9cec 100644
--- a/fs/ocfs2/ocfs2_lockid.h
+++ b/fs/ocfs2/ocfs2_lockid.h
@@ -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
index 00000000000..7365e2e0870
--- /dev/null
+++ b/fs/ocfs2/quota.h
@@ -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
index 00000000000..6aff8f2d3e4
--- /dev/null
+++ b/fs/ocfs2/quota_global.c
@@ -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
index 00000000000..07deec5e972
--- /dev/null
+++ b/fs/ocfs2/quota_local.c
@@ -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
+};
diff --git a/fs/ocfs2/resize.c b/fs/ocfs2/resize.c
index ffd48db229a..424adaa5f90 100644
--- a/fs/ocfs2/resize.c
+++ b/fs/ocfs2/resize.c
@@ -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;
diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c
index bdda2d8f850..40661e7824e 100644
--- a/fs/ocfs2/slot_map.c
+++ b/fs/ocfs2/slot_map.c
@@ -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;
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index c5ff18b46b5..a69628603e1 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -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;
diff --git a/fs/ocfs2/suballoc.h b/fs/ocfs2/suballoc.h
index 4df159d8f45..e3c13c77f9e 100644
--- a/fs/ocfs2/suballoc.h
+++ b/fs/ocfs2/suballoc.h
@@ -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,
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 304b63ac78c..43ed11345b5 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -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"
@@ -65,10 +67,13 @@
#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;
}
diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c
index cbd03dfdc7b..ed0a0cfd68d 100644
--- a/fs/ocfs2/symlink.c
+++ b/fs/ocfs2/symlink.c
@@ -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);
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 74d7367ade1..e1d638af6ac 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -35,12 +35,14 @@
#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,6 +1142,32 @@ 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);
+
+ 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 name_index,
+ const char *name,
+ void *buffer,
+ size_t buffer_size)
+{
+ 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);
@@ -877,44 +1176,36 @@ static int ocfs2_xattr_get(struct inode *inode,
}
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, credits;
+ 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;
- ret = ocfs2_read_block(inode, p_blkno, &bh);
+ search = ocfs2_xattr_bucket_new(inode);
+ if (!search) {
+ ret = -ENOMEM;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ 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 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_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_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,10 +3944,8 @@ 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);
@@ -3387,92 +3953,115 @@ static int ocfs2_cp_xattr_bucket(struct inode *inode,
(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;
+ 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, s_blkno, s_bhs, 0);
+ ret = ocfs2_read_xattr_bucket(s_bucket, s_blkno);
if (ret)
goto out;
- t_bhs = kzalloc(sizeof(struct buffer_head *) * blk_per_bucket,
- GFP_NOFS);
- if (!t_bhs) {
- ret = -ENOMEM;
+ /*
+ * 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;
- }
- ret = ocfs2_read_xattr_bucket(inode, t_blkno, t_bhs, t_is_new);
+ /*
+ * 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;
- 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;
- }
-
- 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]);
- }
+ ocfs2_xattr_bucket_copy_data(t_bucket, s_bucket);
+ ocfs2_xattr_bucket_journal_dirty(handle, t_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(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);
+ }
+
+ /* 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;
+ }
- mlog(0, "cp xattrs from cluster %llu to %llu\n",
- (unsigned long long)src_blk, (unsigned long long)to_blk);
+ 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.
+ *
+ * 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.
*
- * 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.
+ * 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;
}
@@ -4768,6 +5284,74 @@ out:
}
/*
+ * '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
*/
static size_t ocfs2_xattr_trusted_list(struct inode *inode, char *list,
diff --git a/fs/ocfs2/xattr.h b/fs/ocfs2/xattr.h
index 1d8314c7656..5a1ebc789f7 100644
--- a/fs/ocfs2/xattr.h
+++ b/fs/ocfs2/xattr.h
@@ -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 */
diff --git a/fs/omfs/inode.c b/fs/omfs/inode.c
index 6afe57c84f8..633e9dc972b 100644
--- a/fs/omfs/inode.c
+++ b/fs/omfs/inode.c
@@ -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;
diff --git a/fs/open.c b/fs/open.c
index 1cd7d40e999..d882fd2351d 100644
--- 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;
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
index d41bdc784de..ffcd04f0012 100644
--- a/fs/openpromfs/inode.c
+++ b/fs/openpromfs/inode.c
@@ -256,9 +256,6 @@ found:
break;
}
- inode->i_gid = 0;
- inode->i_uid = 0;
-
d_add(dentry, inode);
return NULL;
}
diff --git a/fs/pipe.c b/fs/pipe.c
index aaf797bd57b..891697112f6 100644
--- 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:
diff --git a/fs/proc/base.c b/fs/proc/base.c
index cad92c1ac2b..10fd5223d60 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -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;
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 06ed10b7da9..94fcfff6863 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -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;
diff --git a/fs/quota.c b/fs/quota.c
index b7fe44e0161..4a8c94f05f7 100644
--- a/fs/quota.c
+++ b/fs/quota.c
@@ -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
index 00000000000..953404c95b1
--- /dev/null
+++ b/fs/quota_tree.c
@@ -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
index 00000000000..a1ab8db81a5
--- /dev/null
+++ b/fs/quota_tree.h
@@ -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 */
diff --git a/fs/quota_v1.c b/fs/quota_v1.c
index 5ae15b13eeb..b4af1c69ad1 100644
--- a/fs/quota_v1.c
+++ b/fs/quota_v1.c
@@ -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;
}
diff --git a/fs/quota_v2.c b/fs/quota_v2.c
index b53827dc02d..b618b563635 100644
--- a/fs/quota_v2.c
+++ b/fs/quota_v2.c
@@ -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>
@@ -15,16 +14,37 @@
#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,
diff --git a/include/linux/quotaio_v1.h b/fs/quotaio_v1.h
index 746654b5de7..746654b5de7 100644
--- a/include/linux/quotaio_v1.h
+++ b/fs/quotaio_v1.h
diff --git a/include/linux/quotaio_v2.h b/fs/quotaio_v2.h
index 303d7cbe30d..530fe580685 100644
--- a/include/linux/quotaio_v2.h
+++ b/fs/quotaio_v2.h
@@ -21,6 +21,12 @@
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 */
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index a83a3518ae3..b7e6ac706b8 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -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);
diff --git a/fs/read_write.c b/fs/read_write.c
index 969a6d9c020..5cc6924eb15 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -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;
}
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 145c2d3e5e0..55fce92cdf1 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -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;
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 663a91f5dce..c55651f1407 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -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;
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c
index 60d2f822e87..c97d4c93171 100644
--- a/fs/romfs/inode.c
+++ b/fs/romfs/inode.c
@@ -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);
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index e4f8d51a555..92d5e8ffb63 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -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;
diff --git a/fs/stat.c b/fs/stat.c
index 7c46fbeb8b7..7e12a6f8279 100644
--- 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);
diff --git a/fs/sync.c b/fs/sync.c
index 2967562d416..0921d6d4b5e 100644
--- 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);
}
/*
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index eb53c632f85..dfa3d94cfc7 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -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;
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index fe82d2464d4..bf37374567f 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -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,7 +248,7 @@ 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;
@@ -438,7 +439,7 @@ 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;
@@ -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);
}
/*
diff --git a/fs/xattr.c b/fs/xattr.c
index 468377e6653..237804cd6b5 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -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);
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 95ac82340c3..39da666067b 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -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
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 26c4f6f65a4..67e5dbfc296 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -247,6 +247,18 @@
#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
diff --git a/include/linux/blockgroup_lock.h b/include/linux/blockgroup_lock.h
index 8607312983b..e44b88ba552 100644
--- a/include/linux/blockgroup_lock.h
+++ b/include/linux/blockgroup_lock.h
@@ -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
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 1ee608fd7b7..484b3abf61b 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -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 */
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index c17fd334e57..8209e08969f 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -45,6 +45,8 @@ typedef void (*dm_dtr_fn) (struct dm_target *ti);
*/
typedef int (*dm_map_fn) (struct dm_target *ti, struct bio *bio,
union map_info *map_context);
+typedef int (*dm_map_request_fn) (struct dm_target *ti, struct request *clone,
+ union map_info *map_context);
/*
* Returns:
@@ -57,6 +59,9 @@ typedef int (*dm_map_fn) (struct dm_target *ti, struct bio *bio,
typedef int (*dm_endio_fn) (struct dm_target *ti,
struct bio *bio, int error,
union map_info *map_context);
+typedef int (*dm_request_endio_fn) (struct dm_target *ti,
+ struct request *clone, int error,
+ union map_info *map_context);
typedef void (*dm_flush_fn) (struct dm_target *ti);
typedef void (*dm_presuspend_fn) (struct dm_target *ti);
@@ -75,6 +80,13 @@ typedef int (*dm_ioctl_fn) (struct dm_target *ti, unsigned int cmd,
typedef int (*dm_merge_fn) (struct dm_target *ti, struct bvec_merge_data *bvm,
struct bio_vec *biovec, int max_size);
+/*
+ * Returns:
+ * 0: The target can handle the next I/O immediately.
+ * 1: The target can't handle the next I/O immediately.
+ */
+typedef int (*dm_busy_fn) (struct dm_target *ti);
+
void dm_error(const char *message);
/*
@@ -100,14 +112,23 @@ void dm_put_device(struct dm_target *ti, struct dm_dev *d);
/*
* Information about a target type
*/
+
+/*
+ * Target features
+ */
+#define DM_TARGET_SUPPORTS_BARRIERS 0x00000001
+
struct target_type {
+ uint64_t features;
const char *name;
struct module *module;
unsigned version[3];
dm_ctr_fn ctr;
dm_dtr_fn dtr;
dm_map_fn map;
+ dm_map_request_fn map_rq;
dm_endio_fn end_io;
+ dm_request_endio_fn rq_end_io;
dm_flush_fn flush;
dm_presuspend_fn presuspend;
dm_postsuspend_fn postsuspend;
@@ -117,6 +138,7 @@ struct target_type {
dm_message_fn message;
dm_ioctl_fn ioctl;
dm_merge_fn merge;
+ dm_busy_fn busy;
};
struct io_restrictions {
@@ -157,8 +179,7 @@ struct dm_target {
};
int dm_register_target(struct target_type *t);
-int dm_unregister_target(struct target_type *t);
-
+void dm_unregister_target(struct target_type *t);
/*-----------------------------------------------------------------
* Functions for creating and manipulating mapped devices.
@@ -276,6 +297,9 @@ void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size);
*---------------------------------------------------------------*/
#define DM_NAME "device-mapper"
+#define DMCRIT(f, arg...) \
+ printk(KERN_CRIT DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
+
#define DMERR(f, arg...) \
printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
#define DMERR_LIMIT(f, arg...) \
diff --git a/include/linux/dma_remapping.h b/include/linux/dma_remapping.h
index 136f170cecc..af1dab41674 100644
--- a/include/linux/dma_remapping.h
+++ b/include/linux/dma_remapping.h
@@ -17,7 +17,15 @@ struct dmar_domain;
struct root_entry;
extern void free_dmar_iommu(struct intel_iommu *iommu);
+
+#ifdef CONFIG_DMAR
extern int iommu_calculate_agaw(struct intel_iommu *iommu);
+#else
+static inline int iommu_calculate_agaw(struct intel_iommu *iommu)
+{
+ return 0;
+}
+#endif
extern int dmar_disabled;
diff --git a/include/linux/dqblk_qtree.h b/include/linux/dqblk_qtree.h
new file mode 100644
index 00000000000..82a16527b36
--- /dev/null
+++ b/include/linux/dqblk_qtree.h
@@ -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 */
diff --git a/include/linux/dqblk_v1.h b/include/linux/dqblk_v1.h
index 57f1250d5a5..3713a7232dd 100644
--- a/include/linux/dqblk_v1.h
+++ b/include/linux/dqblk_v1.h
@@ -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 */
diff --git a/include/linux/dqblk_v2.h b/include/linux/dqblk_v2.h
index 4f853322cb7..18000a54267 100644
--- a/include/linux/dqblk_v2.h
+++ b/include/linux/dqblk_v2.h
@@ -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 */
diff --git a/include/linux/ext2_fs_sb.h b/include/linux/ext2_fs_sb.h
index f273415ab6f..dc541f3653d 100644
--- a/include/linux/ext2_fs_sb.h
+++ b/include/linux/ext2_fs_sb.h
@@ -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 */
diff --git a/include/linux/ext3_fs_sb.h b/include/linux/ext3_fs_sb.h
index b65f0288b84..e024e38248f 100644
--- a/include/linux/ext3_fs_sb.h
+++ b/include/linux/ext3_fs_sb.h
@@ -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 */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index e2170ee21e1..fb59673c60b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -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);
@@ -2056,6 +2059,9 @@ extern int vfs_fstat(unsigned int, struct kstat *);
extern int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
unsigned long arg);
+extern int __generic_block_fiemap(struct inode *inode,
+ struct fiemap_extent_info *fieinfo, u64 start,
+ u64 len, get_block_t *get_block);
extern int generic_block_fiemap(struct inode *inode,
struct fiemap_extent_info *fieinfo, u64 start,
u64 len, get_block_t *get_block);
diff --git a/include/linux/hid.h b/include/linux/hid.h
index e5780f8c934..81aa84d60c6 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -403,15 +403,6 @@ struct hid_output_fifo {
#define HID_STAT_ADDED 1
#define HID_STAT_PARSED 2
-#define HID_CTRL_RUNNING 1
-#define HID_OUT_RUNNING 2
-#define HID_IN_RUNNING 3
-#define HID_RESET_PENDING 4
-#define HID_SUSPENDED 5
-#define HID_CLEAR_HALT 6
-#define HID_DISCONNECTED 7
-#define HID_STARTED 8
-
struct hid_input {
struct list_head list;
struct hid_report *report;
@@ -540,6 +531,8 @@ struct hid_usage_id {
* @name: driver name (e.g. "Footech_bar-wheel")
* @id_table: which devices is this driver for (must be non-NULL for probe
* to be called)
+ * @dyn_list: list of dynamically added device ids
+ * @dyn_lock: lock protecting @dyn_list
* @probe: new device inserted
* @remove: device removed (NULL if not a hot-plug capable driver)
* @report_table: on which reports to call raw_event (NULL means all)
@@ -567,6 +560,9 @@ struct hid_driver {
char *name;
const struct hid_device_id *id_table;
+ struct list_head dyn_list;
+ spinlock_t dyn_lock;
+
int (*probe)(struct hid_device *dev, const struct hid_device_id *id);
void (*remove)(struct hid_device *dev);
@@ -797,6 +793,8 @@ dbg_hid(const char *fmt, ...)
#ifdef CONFIG_HID_COMPAT
#define HID_COMPAT_LOAD_DRIVER(name) \
+/* prototype to avoid sparse warning */ \
+extern void hid_compat_##name(void); \
void hid_compat_##name(void) { } \
EXPORT_SYMBOL(hid_compat_##name)
#else
diff --git a/include/linux/hidraw.h b/include/linux/hidraw.h
index dbb5c8c374f..dd8d6926917 100644
--- a/include/linux/hidraw.h
+++ b/include/linux/hidraw.h
@@ -33,6 +33,8 @@ struct hidraw_devinfo {
#define HIDIOCGRDESCSIZE _IOR('H', 0x01, int)
#define HIDIOCGRDESC _IOR('H', 0x02, struct hidraw_report_descriptor)
#define HIDIOCGRAWINFO _IOR('H', 0x03, struct hidraw_devinfo)
+#define HIDIOCGRAWNAME(len) _IOC(_IOC_READ, 'H', 0x04, len)
+#define HIDIOCGRAWPHYS(len) _IOC(_IOC_READ, 'H', 0x05, len)
#define HIDRAW_FIRST_MINOR 0
#define HIDRAW_MAX_DEVICES 64
diff --git a/include/linux/i2c/dm355evm_msp.h b/include/linux/i2c/dm355evm_msp.h
new file mode 100644
index 00000000000..372470350fa
--- /dev/null
+++ b/include/linux/i2c/dm355evm_msp.h
@@ -0,0 +1,79 @@
+/*
+ * dm355evm_msp.h - support MSP430 microcontroller on DM355EVM board
+ */
+#ifndef __LINUX_I2C_DM355EVM_MSP
+#define __LINUX_I2C_DM355EVM_MSP
+
+/*
+ * Written against Spectrum's writeup for the A4 firmware revision,
+ * and tweaked to match source and rev D2 schematics by removing CPLD
+ * and NOR flash hooks (which were last appropriate in rev B boards).
+ *
+ * Note that the firmware supports a flavor of write posting ... to be
+ * sure a write completes, issue another read or write.
+ */
+
+/* utilities to access "registers" emulated by msp430 firmware */
+extern int dm355evm_msp_write(u8 value, u8 reg);
+extern int dm355evm_msp_read(u8 reg);
+
+
+/* command/control registers */
+#define DM355EVM_MSP_COMMAND 0x00
+# define MSP_COMMAND_NULL 0
+# define MSP_COMMAND_RESET_COLD 1
+# define MSP_COMMAND_RESET_WARM 2
+# define MSP_COMMAND_RESET_WARM_I 3
+# define MSP_COMMAND_POWEROFF 4
+# define MSP_COMMAND_IR_REINIT 5
+#define DM355EVM_MSP_STATUS 0x01
+# define MSP_STATUS_BAD_OFFSET BIT(0)
+# define MSP_STATUS_BAD_COMMAND BIT(1)
+# define MSP_STATUS_POWER_ERROR BIT(2)
+# define MSP_STATUS_RXBUF_OVERRUN BIT(3)
+#define DM355EVM_MSP_RESET 0x02 /* 0 bits == in reset */
+# define MSP_RESET_DC5 BIT(0)
+# define MSP_RESET_TVP5154 BIT(2)
+# define MSP_RESET_IMAGER BIT(3)
+# define MSP_RESET_ETHERNET BIT(4)
+# define MSP_RESET_SYS BIT(5)
+# define MSP_RESET_AIC33 BIT(7)
+
+/* GPIO registers ... bit patterns mostly match the source MSP ports */
+#define DM355EVM_MSP_LED 0x03 /* active low (MSP P4) */
+#define DM355EVM_MSP_SWITCH1 0x04 /* (MSP P5, masked) */
+# define MSP_SWITCH1_SW6_1 BIT(0)
+# define MSP_SWITCH1_SW6_2 BIT(1)
+# define MSP_SWITCH1_SW6_3 BIT(2)
+# define MSP_SWITCH1_SW6_4 BIT(3)
+# define MSP_SWITCH1_J1 BIT(4) /* NTSC/PAL */
+# define MSP_SWITCH1_MSP_INT BIT(5) /* active low */
+#define DM355EVM_MSP_SWITCH2 0x05 /* (MSP P6, masked) */
+# define MSP_SWITCH2_SW10 BIT(3)
+# define MSP_SWITCH2_SW11 BIT(4)
+# define MSP_SWITCH2_SW12 BIT(5)
+# define MSP_SWITCH2_SW13 BIT(6)
+# define MSP_SWITCH2_SW14 BIT(7)
+#define DM355EVM_MSP_SDMMC 0x06 /* (MSP P2, masked) */
+# define MSP_SDMMC_0_WP BIT(1)
+# define MSP_SDMMC_0_CD BIT(2) /* active low */
+# define MSP_SDMMC_1_WP BIT(3)
+# define MSP_SDMMC_1_CD BIT(4) /* active low */
+#define DM355EVM_MSP_FIRMREV 0x07 /* not a GPIO (out of order) */
+#define DM355EVM_MSP_VIDEO_IN 0x08 /* (MSP P3, masked) */
+# define MSP_VIDEO_IMAGER BIT(7) /* low == tvp5146 */
+
+/* power supply registers are currently omitted */
+
+/* RTC registers */
+#define DM355EVM_MSP_RTC_0 0x12 /* LSB */
+#define DM355EVM_MSP_RTC_1 0x13
+#define DM355EVM_MSP_RTC_2 0x14
+#define DM355EVM_MSP_RTC_3 0x15 /* MSB */
+
+/* input event queue registers; code == ((HIGH << 8) | LOW) */
+#define DM355EVM_MSP_INPUT_COUNT 0x16 /* decrement by reading LOW */
+#define DM355EVM_MSP_INPUT_HIGH 0x17
+#define DM355EVM_MSP_INPUT_LOW 0x18
+
+#endif /* __LINUX_I2C_DM355EVM_MSP */
diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl4030.h
index fb604dcd38f..a8f84c01f82 100644
--- a/include/linux/i2c/twl4030.h
+++ b/include/linux/i2c/twl4030.h
@@ -78,8 +78,8 @@ int twl4030_i2c_read_u8(u8 mod_no, u8 *val, u8 reg);
* IMPORTANT: For twl4030_i2c_write(), allocate num_bytes + 1
* for the value, and populate your data starting at offset 1.
*/
-int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, u8 num_bytes);
-int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, u8 num_bytes);
+int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes);
+int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes);
/*----------------------------------------------------------------------*/
@@ -278,6 +278,18 @@ struct twl4030_platform_data {
struct twl4030_keypad_data *keypad;
struct twl4030_usb_data *usb;
+ /* LDO regulators */
+ struct regulator_init_data *vdac;
+ struct regulator_init_data *vpll1;
+ struct regulator_init_data *vpll2;
+ struct regulator_init_data *vmmc1;
+ struct regulator_init_data *vmmc2;
+ struct regulator_init_data *vsim;
+ struct regulator_init_data *vaux1;
+ struct regulator_init_data *vaux2;
+ struct regulator_init_data *vaux3;
+ struct regulator_init_data *vaux4;
+
/* REVISIT more to come ... _nothing_ should be hard-wired */
};
@@ -285,33 +297,6 @@ struct twl4030_platform_data {
int twl4030_sih_setup(int module);
-/*
- * FIXME completely stop using TWL4030_IRQ_BASE ... instead, pass the
- * IRQ data to subsidiary devices using platform device resources.
- */
-
-/* IRQ information-need base */
-#include <mach/irqs.h>
-/* TWL4030 interrupts */
-
-/* #define TWL4030_MODIRQ_GPIO (TWL4030_IRQ_BASE + 0) */
-#define TWL4030_MODIRQ_KEYPAD (TWL4030_IRQ_BASE + 1)
-#define TWL4030_MODIRQ_BCI (TWL4030_IRQ_BASE + 2)
-#define TWL4030_MODIRQ_MADC (TWL4030_IRQ_BASE + 3)
-/* #define TWL4030_MODIRQ_USB (TWL4030_IRQ_BASE + 4) */
-/* #define TWL4030_MODIRQ_PWR (TWL4030_IRQ_BASE + 5) */
-
-#define TWL4030_PWRIRQ_PWRBTN (TWL4030_PWR_IRQ_BASE + 0)
-/* #define TWL4030_PWRIRQ_CHG_PRES (TWL4030_PWR_IRQ_BASE + 1) */
-/* #define TWL4030_PWRIRQ_USB_PRES (TWL4030_PWR_IRQ_BASE + 2) */
-/* #define TWL4030_PWRIRQ_RTC (TWL4030_PWR_IRQ_BASE + 3) */
-/* #define TWL4030_PWRIRQ_HOT_DIE (TWL4030_PWR_IRQ_BASE + 4) */
-/* #define TWL4030_PWRIRQ_PWROK_TIMEOUT (TWL4030_PWR_IRQ_BASE + 5) */
-/* #define TWL4030_PWRIRQ_MBCHG (TWL4030_PWR_IRQ_BASE + 6) */
-/* #define TWL4030_PWRIRQ_SC_DETECT (TWL4030_PWR_IRQ_BASE + 7) */
-
-/* Rest are unsued currently*/
-
/* Offsets to Power Registers */
#define TWL4030_VDAC_DEV_GRP 0x3B
#define TWL4030_VDAC_DEDICATED 0x3E
@@ -322,10 +307,6 @@ int twl4030_sih_setup(int module);
#define TWL4030_VAUX3_DEV_GRP 0x1F
#define TWL4030_VAUX3_DEDICATED 0x22
-/* TWL4030 GPIO interrupt definitions */
-
-#define TWL4030_GPIO_IRQ_NO(n) (TWL4030_GPIO_IRQ_BASE + (n))
-
/*
* Exported TWL4030 GPIO APIs
*
@@ -340,4 +321,38 @@ int twl4030_set_gpio_debounce(int gpio, int enable);
static inline int twl4030charger_usb_en(int enable) { return 0; }
#endif
+/*----------------------------------------------------------------------*/
+
+/* Linux-specific regulator identifiers ... for now, we only support
+ * the LDOs, and leave the three buck converters alone. VDD1 and VDD2
+ * need to tie into hardware based voltage scaling (cpufreq etc), while
+ * VIO is generally fixed.
+ */
+
+/* EXTERNAL dc-to-dc buck converters */
+#define TWL4030_REG_VDD1 0
+#define TWL4030_REG_VDD2 1
+#define TWL4030_REG_VIO 2
+
+/* EXTERNAL LDOs */
+#define TWL4030_REG_VDAC 3
+#define TWL4030_REG_VPLL1 4
+#define TWL4030_REG_VPLL2 5 /* not on all chips */
+#define TWL4030_REG_VMMC1 6
+#define TWL4030_REG_VMMC2 7 /* not on all chips */
+#define TWL4030_REG_VSIM 8 /* not on all chips */
+#define TWL4030_REG_VAUX1 9 /* not on all chips */
+#define TWL4030_REG_VAUX2_4030 10 /* (twl4030-specific) */
+#define TWL4030_REG_VAUX2 11 /* (twl5030 and newer) */
+#define TWL4030_REG_VAUX3 12 /* not on all chips */
+#define TWL4030_REG_VAUX4 13 /* not on all chips */
+
+/* INTERNAL LDOs */
+#define TWL4030_REG_VINTANA1 14
+#define TWL4030_REG_VINTANA2 15
+#define TWL4030_REG_VINTDIG 16
+#define TWL4030_REG_VUSB1V5 17
+#define TWL4030_REG_VUSB1V8 18
+#define TWL4030_REG_VUSB3V1 19
+
#endif /* End of __TWL4030_H */
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index c7d106ef22e..34456476e76 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -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 *);
diff --git a/include/linux/journal-head.h b/include/linux/journal-head.h
index bb70ebb6a2d..525aac3c97d 100644
--- a/include/linux/journal-head.h
+++ b/include/linux/journal-head.h
@@ -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 */
diff --git a/include/linux/mfd/da903x.h b/include/linux/mfd/da903x.h
index cad314c1243..115dbe96508 100644
--- a/include/linux/mfd/da903x.h
+++ b/include/linux/mfd/da903x.h
@@ -32,6 +32,7 @@ enum {
DA9030_ID_LDO18,
DA9030_ID_LDO19,
DA9030_ID_LDO_INT, /* LDO Internal */
+ DA9030_ID_BAT, /* battery charger */
DA9034_ID_LED_1,
DA9034_ID_LED_2,
@@ -93,6 +94,43 @@ struct da9034_touch_pdata {
int y_inverted;
};
+/* DA9030 battery charger data */
+struct power_supply_info;
+
+struct da9030_battery_info {
+ /* battery parameters */
+ struct power_supply_info *battery_info;
+
+ /* current and voltage to use for battery charging */
+ unsigned int charge_milliamp;
+ unsigned int charge_millivolt;
+
+ /* voltage thresholds (in millivolts) */
+ int vbat_low;
+ int vbat_crit;
+ int vbat_charge_start;
+ int vbat_charge_stop;
+ int vbat_charge_restart;
+
+ /* battery nominal minimal and maximal voltages in millivolts */
+ int vcharge_min;
+ int vcharge_max;
+
+ /* Temperature thresholds. These are DA9030 register values
+ "as is" and should be measured for each battery type */
+ int tbat_low;
+ int tbat_high;
+ int tbat_restart;
+
+
+ /* battery monitor interval (seconds) */
+ unsigned int batmon_interval;
+
+ /* platform callbacks for battery low and critical events */
+ void (*battery_low)(void);
+ void (*battery_critical)(void);
+};
+
struct da903x_subdev_info {
int id;
const char *name;
@@ -190,11 +228,13 @@ extern int da903x_unregister_notifier(struct device *dev,
extern int da903x_query_status(struct device *dev, unsigned int status);
-/* NOTE: the two functions below are not intended for use outside
- * of the DA9034 sub-device drivers
+/* NOTE: the functions below are not intended for use outside
+ * of the DA903x sub-device drivers
*/
extern int da903x_write(struct device *dev, int reg, uint8_t val);
+extern int da903x_writes(struct device *dev, int reg, int len, uint8_t *val);
extern int da903x_read(struct device *dev, int reg, uint8_t *val);
+extern int da903x_reads(struct device *dev, int reg, int len, uint8_t *val);
extern int da903x_update(struct device *dev, int reg, uint8_t val, uint8_t mask);
extern int da903x_set_bits(struct device *dev, int reg, uint8_t bit_mask);
extern int da903x_clr_bits(struct device *dev, int reg, uint8_t bit_mask);
diff --git a/include/linux/mfd/wm8350/comparator.h b/include/linux/mfd/wm8350/comparator.h
index 05378864945..54bc5d0fd50 100644
--- a/include/linux/mfd/wm8350/comparator.h
+++ b/include/linux/mfd/wm8350/comparator.h
@@ -164,4 +164,12 @@
#define WM8350_AUXADC_BATT 6
#define WM8350_AUXADC_TEMP 7
+struct wm8350;
+
+/*
+ * AUX ADC Readback
+ */
+int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale,
+ int vref);
+
#endif
diff --git a/include/linux/mfd/wm8350/core.h b/include/linux/mfd/wm8350/core.h
index 6ebf97f2a47..980669d50dc 100644
--- a/include/linux/mfd/wm8350/core.h
+++ b/include/linux/mfd/wm8350/core.h
@@ -29,6 +29,7 @@
*/
#define WM8350_RESET_ID 0x00
#define WM8350_ID 0x01
+#define WM8350_REVISION 0x02
#define WM8350_SYSTEM_CONTROL_1 0x03
#define WM8350_SYSTEM_CONTROL_2 0x04
#define WM8350_SYSTEM_HIBERNATE 0x05
@@ -57,6 +58,10 @@
#define WM8350_OVER_CURRENT_INT_STATUS_MASK 0x25
#define WM8350_GPIO_INT_STATUS_MASK 0x26
#define WM8350_COMPARATOR_INT_STATUS_MASK 0x27
+#define WM8350_CHARGER_OVERRIDES 0xE2
+#define WM8350_MISC_OVERRIDES 0xE3
+#define WM8350_COMPARATOR_OVERRIDES 0xE7
+#define WM8350_STATE_MACHINE_STATUS 0xE9
#define WM8350_MAX_REGISTER 0xFF
@@ -77,6 +82,11 @@
#define WM8350_CUST_ID_MASK 0x00FF
/*
+ * R2 (0x02) - Revision
+ */
+#define WM8350_MASK_REV_MASK 0x00FF
+
+/*
* R3 (0x03) - System Control 1
*/
#define WM8350_CHIP_ON 0x8000
@@ -523,6 +533,35 @@
#define WM8350_DC2_STS 0x0002
#define WM8350_DC1_STS 0x0001
+/*
+ * R226 (0xE2) - Charger status
+ */
+#define WM8350_CHG_BATT_HOT_OVRDE 0x8000
+#define WM8350_CHG_BATT_COLD_OVRDE 0x4000
+
+/*
+ * R227 (0xE3) - Misc Overrides
+ */
+#define WM8350_USB_LIMIT_OVRDE 0x0400
+
+/*
+ * R227 (0xE7) - Comparator Overrides
+ */
+#define WM8350_USB_FB_OVRDE 0x8000
+#define WM8350_WALL_FB_OVRDE 0x4000
+#define WM8350_BATT_FB_OVRDE 0x2000
+
+
+/*
+ * R233 (0xE9) - State Machinine Status
+ */
+#define WM8350_USB_SM_MASK 0x0700
+#define WM8350_USB_SM_SHIFT 8
+
+#define WM8350_USB_SM_100_SLV 1
+#define WM8350_USB_SM_500_SLV 5
+#define WM8350_USB_SM_STDBY_SLV 7
+
/* WM8350 wake up conditions */
#define WM8350_IRQ_WKUP_OFF_STATE 43
#define WM8350_IRQ_WKUP_HIB_STATE 44
@@ -536,6 +575,7 @@
#define WM8350_REV_E 0x4
#define WM8350_REV_F 0x5
#define WM8350_REV_G 0x6
+#define WM8350_REV_H 0x7
#define WM8350_NUM_IRQ 63
@@ -549,6 +589,14 @@ extern const u16 wm8350_mode0_defaults[];
extern const u16 wm8350_mode1_defaults[];
extern const u16 wm8350_mode2_defaults[];
extern const u16 wm8350_mode3_defaults[];
+extern const u16 wm8351_mode0_defaults[];
+extern const u16 wm8351_mode1_defaults[];
+extern const u16 wm8351_mode2_defaults[];
+extern const u16 wm8351_mode3_defaults[];
+extern const u16 wm8352_mode0_defaults[];
+extern const u16 wm8352_mode1_defaults[];
+extern const u16 wm8352_mode2_defaults[];
+extern const u16 wm8352_mode3_defaults[];
struct wm8350;
@@ -558,8 +606,6 @@ struct wm8350_irq {
};
struct wm8350 {
- int rev; /* chip revision */
-
struct device *dev;
/* device IO */
@@ -572,6 +618,8 @@ struct wm8350 {
void *src);
u16 *reg_cache;
+ struct mutex auxadc_mutex;
+
/* Interrupt handling */
struct work_struct irq_work;
struct mutex irq_mutex; /* IRQ table mutex */
diff --git a/include/linux/mfd/wm8350/pmic.h b/include/linux/mfd/wm8350/pmic.h
index 69b69e07f62..96acbfc8aa1 100644
--- a/include/linux/mfd/wm8350/pmic.h
+++ b/include/linux/mfd/wm8350/pmic.h
@@ -701,6 +701,10 @@ struct platform_device;
struct regulator_init_data;
struct wm8350_pmic {
+ /* Number of regulators of each type on this device */
+ int max_dcdc;
+ int max_isink;
+
/* ISINK to DCDC mapping */
int isink_A_dcdc;
int isink_B_dcdc;
diff --git a/include/linux/mfd/wm8350/supply.h b/include/linux/mfd/wm8350/supply.h
index 1c8f3cde79b..2b9479310bb 100644
--- a/include/linux/mfd/wm8350/supply.h
+++ b/include/linux/mfd/wm8350/supply.h
@@ -13,7 +13,8 @@
#ifndef __LINUX_MFD_WM8350_SUPPLY_H_
#define __LINUX_MFD_WM8350_SUPPLY_H_
-#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/power_supply.h>
/*
* Charger registers
@@ -104,8 +105,30 @@
#define WM8350_IRQ_EXT_WALL_FB 37
#define WM8350_IRQ_EXT_BAT_FB 38
+/*
+ * Policy to control charger state machine.
+ */
+struct wm8350_charger_policy {
+
+ /* charger state machine policy - set in machine driver */
+ int eoc_mA; /* end of charge current (mA) */
+ int charge_mV; /* charge voltage */
+ int fast_limit_mA; /* fast charge current limit */
+ int fast_limit_USB_mA; /* USB fast charge current limit */
+ int charge_timeout; /* charge timeout (mins) */
+ int trickle_start_mV; /* trickle charge starts at mV */
+ int trickle_charge_mA; /* trickle charge current */
+ int trickle_charge_USB_mA; /* USB trickle charge current */
+};
+
struct wm8350_power {
struct platform_device *pdev;
+ struct power_supply battery;
+ struct power_supply usb;
+ struct power_supply ac;
+ struct wm8350_charger_policy *policy;
+
+ int rev_g_coeff;
};
#endif
diff --git a/include/linux/moduleloader.h b/include/linux/moduleloader.h
index eb103395748..c1f40c2f7ff 100644
--- a/include/linux/moduleloader.h
+++ b/include/linux/moduleloader.h
@@ -13,6 +13,9 @@ int module_frob_arch_sections(Elf_Ehdr *hdr,
char *secstrings,
struct module *mod);
+/* Additional bytes needed by arch in front of individual sections */
+unsigned int arch_mod_section_prepend(struct module *mod, unsigned int section);
+
/* Allocator used for allocating struct module, core sections and init
sections. Returns NULL on failure. */
void *module_alloc(unsigned long size);
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 41e1224651c..c28bbba3c23 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -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 *);
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 709742be02f..01ca0856caf 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -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.
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index f9348cba6dc..8ff25e0e7f7 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -45,6 +45,7 @@ enum {
POWER_SUPPLY_HEALTH_DEAD,
POWER_SUPPLY_HEALTH_OVERVOLTAGE,
POWER_SUPPLY_HEALTH_UNSPEC_FAILURE,
+ POWER_SUPPLY_HEALTH_COLD,
};
enum {
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 40401b55448..d72d5d84fde 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -36,17 +36,7 @@
#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 */
@@ -80,16 +70,34 @@
#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 */
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index a558a4c1d35..21b781a3350 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -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.
*/
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index a916c6660df..355f6e80db0 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -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;
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index 91f597ad6ac..4046b75563c 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -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);
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 4be01bb4437..82229317753 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -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...)
diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h
index 74d59a64136..baba3a23a81 100644
--- a/include/linux/stop_machine.h
+++ b/include/linux/stop_machine.h
@@ -35,6 +35,24 @@ int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus);
* won't come or go while it's being called. Used by hotplug cpu.
*/
int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus);
+
+/**
+ * stop_machine_create: create all stop_machine threads
+ *
+ * Description: This causes all stop_machine threads to be created before
+ * stop_machine actually gets called. This can be used by subsystems that
+ * need a non failing stop_machine infrastructure.
+ */
+int stop_machine_create(void);
+
+/**
+ * stop_machine_destroy: destroy all stop_machine threads
+ *
+ * Description: This causes all stop_machine threads which were created with
+ * stop_machine_create to be destroyed again.
+ */
+void stop_machine_destroy(void);
+
#else
static inline int stop_machine(int (*fn)(void *), void *data,
@@ -46,5 +64,9 @@ static inline int stop_machine(int (*fn)(void *), void *data,
local_irq_enable();
return ret;
}
+
+static inline int stop_machine_create(void) { return 0; }
+static inline void stop_machine_destroy(void) { }
+
#endif /* CONFIG_SMP */
#endif /* _LINUX_STOP_MACHINE */
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 04fb47bfb92..18d0a243a7b 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -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);
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index ce532f2222c..1459ed3e269 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -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);
}
diff --git a/init/Kconfig b/init/Kconfig
index f6281711166..52847eec739 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -916,12 +916,6 @@ config MODULE_SRCVERSION_ALL
the version). With this option, such a "srcversion" field
will be created for all modules. If unsure, say N.
-config KMOD
- def_bool y
- help
- This is being removed soon. These days, CONFIG_MODULES
- implies CONFIG_KMOD, so use that instead.
-
endif # MODULES
config INIT_ALL_POSSIBLE
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index d9393f8e4c3..eddb6247a55 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -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
diff --git a/ipc/sem.c b/ipc/sem.c
index 082122469b1..fea0ad3aed7 100644
--- 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>
*
diff --git a/ipc/shm.c b/ipc/shm.c
index 38a055758a9..57dd50046ce 100644
--- 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();
diff --git a/ipc/util.c b/ipc/util.c
index 5a1808c774a..7585a72e259 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -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);
diff --git a/kernel/audit.h b/kernel/audit.h
index 9d6717412fe..16f18cac661 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -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
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index 8b509441f49..8ad9545b8db 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -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);
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 9fd85a4640a..fbf24d121d9 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -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;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 4819f371197..8cbddff6c28 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -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;
}
/**
diff --git a/kernel/capability.c b/kernel/capability.c
index 36b4b4daebe..c598d9d5be4 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -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);
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 48348dde6d8..87bb0258fd2 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -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);
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 47fff3b63cb..30e74dd6d01 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -269,8 +269,11 @@ out_release:
int __ref cpu_down(unsigned int cpu)
{
- int err = 0;
+ int err;
+ err = stop_machine_create();
+ if (err)
+ return err;
cpu_maps_update_begin();
if (cpu_hotplug_disabled) {
@@ -297,6 +300,7 @@ int __ref cpu_down(unsigned int cpu)
out:
cpu_maps_update_done();
+ stop_machine_destroy();
return err;
}
EXPORT_SYMBOL(cpu_down);
diff --git a/kernel/module.c b/kernel/module.c
index dd2a54155b5..f47cce910f2 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -757,8 +757,16 @@ sys_delete_module(const char __user *name_user, unsigned int flags)
return -EFAULT;
name[MODULE_NAME_LEN-1] = '\0';
- if (mutex_lock_interruptible(&module_mutex) != 0)
- return -EINTR;
+ /* Create stop_machine threads since free_module relies on
+ * a non-failing stop_machine call. */
+ ret = stop_machine_create();
+ if (ret)
+ return ret;
+
+ if (mutex_lock_interruptible(&module_mutex) != 0) {
+ ret = -EINTR;
+ goto out_stop;
+ }
mod = find_module(name);
if (!mod) {
@@ -817,10 +825,12 @@ sys_delete_module(const char __user *name_user, unsigned int flags)
out:
mutex_unlock(&module_mutex);
+out_stop:
+ stop_machine_destroy();
return ret;
}
-static void print_unload_info(struct seq_file *m, struct module *mod)
+static inline void print_unload_info(struct seq_file *m, struct module *mod)
{
struct module_use *use;
int printed_something = 0;
@@ -893,7 +903,7 @@ void module_put(struct module *module)
EXPORT_SYMBOL(module_put);
#else /* !CONFIG_MODULE_UNLOAD */
-static void print_unload_info(struct seq_file *m, struct module *mod)
+static inline void print_unload_info(struct seq_file *m, struct module *mod)
{
/* We don't know the usage count, or what modules are using. */
seq_printf(m, " - -");
@@ -1578,11 +1588,21 @@ static int simplify_symbols(Elf_Shdr *sechdrs,
return ret;
}
+/* Additional bytes needed by arch in front of individual sections */
+unsigned int __weak arch_mod_section_prepend(struct module *mod,
+ unsigned int section)
+{
+ /* default implementation just returns zero */
+ return 0;
+}
+
/* Update size with this section: return offset. */
-static long get_offset(unsigned int *size, Elf_Shdr *sechdr)
+static long get_offset(struct module *mod, unsigned int *size,
+ Elf_Shdr *sechdr, unsigned int section)
{
long ret;
+ *size += arch_mod_section_prepend(mod, section);
ret = ALIGN(*size, sechdr->sh_addralign ?: 1);
*size = ret + sechdr->sh_size;
return ret;
@@ -1622,7 +1642,7 @@ static void layout_sections(struct module *mod,
|| strncmp(secstrings + s->sh_name,
".init", 5) == 0)
continue;
- s->sh_entsize = get_offset(&mod->core_size, s);
+ s->sh_entsize = get_offset(mod, &mod->core_size, s, i);
DEBUGP("\t%s\n", secstrings + s->sh_name);
}
if (m == 0)
@@ -1640,7 +1660,7 @@ static void layout_sections(struct module *mod,
|| strncmp(secstrings + s->sh_name,
".init", 5) != 0)
continue;
- s->sh_entsize = (get_offset(&mod->init_size, s)
+ s->sh_entsize = (get_offset(mod, &mod->init_size, s, i)
| INIT_OFFSET_MASK);
DEBUGP("\t%s\n", secstrings + s->sh_name);
}
@@ -1725,15 +1745,15 @@ static const struct kernel_symbol *lookup_symbol(const char *name,
return NULL;
}
-static int is_exported(const char *name, const struct module *mod)
+static int is_exported(const char *name, unsigned long value,
+ const struct module *mod)
{
- if (!mod && lookup_symbol(name, __start___ksymtab, __stop___ksymtab))
- return 1;
+ const struct kernel_symbol *ks;
+ if (!mod)
+ ks = lookup_symbol(name, __start___ksymtab, __stop___ksymtab);
else
- if (mod && lookup_symbol(name, mod->syms, mod->syms + mod->num_syms))
- return 1;
- else
- return 0;
+ ks = lookup_symbol(name, mod->syms, mod->syms + mod->num_syms);
+ return ks != NULL && ks->value == value;
}
/* As per nm */
@@ -1865,6 +1885,13 @@ static noinline struct module *load_module(void __user *umod,
/* vmalloc barfs on "unusual" numbers. Check here */
if (len > 64 * 1024 * 1024 || (hdr = vmalloc(len)) == NULL)
return ERR_PTR(-ENOMEM);
+
+ /* Create stop_machine threads since the error path relies on
+ * a non-failing stop_machine call. */
+ err = stop_machine_create();
+ if (err)
+ goto free_hdr;
+
if (copy_from_user(hdr, umod, len) != 0) {
err = -EFAULT;
goto free_hdr;
@@ -2248,6 +2275,7 @@ static noinline struct module *load_module(void __user *umod,
/* Get rid of temporary copy */
vfree(hdr);
+ stop_machine_destroy();
/* Done! */
return mod;
@@ -2270,6 +2298,7 @@ static noinline struct module *load_module(void __user *umod,
kfree(args);
free_hdr:
vfree(hdr);
+ stop_machine_destroy();
return ERR_PTR(err);
truncated:
@@ -2504,7 +2533,7 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
strlcpy(name, mod->strtab + mod->symtab[symnum].st_name,
KSYM_NAME_LEN);
strlcpy(module_name, mod->name, MODULE_NAME_LEN);
- *exported = is_exported(name, mod);
+ *exported = is_exported(name, *value, mod);
preempt_enable();
return 0;
}
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 286c41722e8..0cd415ee62a 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -38,7 +38,10 @@ struct stop_machine_data {
static unsigned int num_threads;
static atomic_t thread_ack;
static DEFINE_MUTEX(lock);
-
+/* setup_lock protects refcount, stop_machine_wq and stop_machine_work. */
+static DEFINE_MUTEX(setup_lock);
+/* Users of stop_machine. */
+static int refcount;
static struct workqueue_struct *stop_machine_wq;
static struct stop_machine_data active, idle;
static const cpumask_t *active_cpus;
@@ -109,6 +112,43 @@ static int chill(void *unused)
return 0;
}
+int stop_machine_create(void)
+{
+ mutex_lock(&setup_lock);
+ if (refcount)
+ goto done;
+ stop_machine_wq = create_rt_workqueue("kstop");
+ if (!stop_machine_wq)
+ goto err_out;
+ stop_machine_work = alloc_percpu(struct work_struct);
+ if (!stop_machine_work)
+ goto err_out;
+done:
+ refcount++;
+ mutex_unlock(&setup_lock);
+ return 0;
+
+err_out:
+ if (stop_machine_wq)
+ destroy_workqueue(stop_machine_wq);
+ mutex_unlock(&setup_lock);
+ return -ENOMEM;
+}
+EXPORT_SYMBOL_GPL(stop_machine_create);
+
+void stop_machine_destroy(void)
+{
+ mutex_lock(&setup_lock);
+ refcount--;
+ if (refcount)
+ goto done;
+ destroy_workqueue(stop_machine_wq);
+ free_percpu(stop_machine_work);
+done:
+ mutex_unlock(&setup_lock);
+}
+EXPORT_SYMBOL_GPL(stop_machine_destroy);
+
int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus)
{
struct work_struct *sm_work;
@@ -146,19 +186,14 @@ int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus)
{
int ret;
+ ret = stop_machine_create();
+ if (ret)
+ return ret;
/* No CPUs can come up or down during this. */
get_online_cpus();
ret = __stop_machine(fn, data, cpus);
put_online_cpus();
-
+ stop_machine_destroy();
return ret;
}
EXPORT_SYMBOL_GPL(stop_machine);
-
-static int __init stop_machine_init(void)
-{
- stop_machine_wq = create_rt_workqueue("kstop");
- stop_machine_work = alloc_percpu(struct work_struct);
- return 0;
-}
-core_initcall(stop_machine_init);
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index fa2dc4e5f9b..7f5e21b9c16 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -23,7 +23,6 @@
#include <linux/spinlock.h>
#include <linux/swiotlb.h>
#include <linux/string.h>
-#include <linux/swiotlb.h>
#include <linux/types.h>
#include <linux/ctype.h>
#include <linux/highmem.h>
@@ -116,7 +115,7 @@ setup_io_tlb_npages(char *str)
__setup("swiotlb=", setup_io_tlb_npages);
/* make io_tlb_overflow tunable too? */
-void * __weak swiotlb_alloc_boot(size_t size, unsigned long nslabs)
+void * __weak __init swiotlb_alloc_boot(size_t size, unsigned long nslabs)
{
return alloc_bootmem_low_pages(size);
}
diff --git a/mm/filemap.c b/mm/filemap.c
index f3e5f8944d1..f5769b4dc07 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -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)
diff --git a/mm/memory.c b/mm/memory.c
index 0a2010a9518..7b9db658aca 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -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);
diff --git a/mm/mmap.c b/mm/mmap.c
index d4855a682ab..2c778fcfd9b 100644
--- 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>
diff --git a/mm/mprotect.c b/mm/mprotect.c
index fded06f923f..cfb4c485206 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -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
*/
diff --git a/mm/mremap.c b/mm/mremap.c
index 58a2908f42f..646de959aa5 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -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
*/
diff --git a/mm/msync.c b/mm/msync.c
index 144a7570535..07dae08cf31 100644
--- a/mm/msync.c
+++ b/mm/msync.c
@@ -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;
diff --git a/mm/nommu.c b/mm/nommu.c
index 7695dc85078..1c28ea3a4e9 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -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:
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 1ddb77ba399..7465f22fec0 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -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;
diff --git a/net/can/bcm.c b/net/can/bcm.c
index da0d426c0ce..6248ae2502c 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -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! */
@@ -541,9 +555,25 @@ static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
}
/*
+ * 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)
diff --git a/net/core/dev.c b/net/core/dev.c
index 09c66a449da..382df6c09ee 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -132,6 +132,9 @@
/* 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;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index b8d0abb2643..5110b359c75 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -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;
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index 5dbfe5fdc0d..8379496de82 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -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;
diff --git a/net/dccp/Kconfig b/net/dccp/Kconfig
index 7aa2a7acc7e..ad6dffd9070 100644
--- a/net/dccp/Kconfig
+++ b/net/dccp/Kconfig
@@ -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"
diff --git a/net/dccp/Makefile b/net/dccp/Makefile
index f4f8793aaff..2991efcc8de 100644
--- a/net/dccp/Makefile
+++ b/net/dccp/Makefile
@@ -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/
diff --git a/net/dccp/ackvec.h b/net/dccp/ackvec.h
index 4ccee030524..45f95e55f87 100644
--- a/net/dccp/ackvec.h
+++ b/net/dccp/ackvec.h
@@ -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 */
diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c
index bcc643f992a..f3e9ba1cfd0 100644
--- a/net/dccp/ccid.c
+++ b/net/dccp/ccid.c
@@ -12,56 +12,70 @@
*/
#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();
+}
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h
index 18f69423a70..facedd20b53 100644
--- a/net/dccp/ccid.h
+++ b/net/dccp/ccid.h
@@ -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)
{
diff --git a/net/dccp/ccids/Kconfig b/net/dccp/ccids/Kconfig
index 12275943eab..b28bf962edc 100644
--- a/net/dccp/ccids/Kconfig
+++ b/net/dccp/ccids/Kconfig
@@ -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
index 438f20bccff..00000000000
--- a/net/dccp/ccids/Makefile
+++ /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/
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
index c9ea19a4d85..d235294ace2 100644
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -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");
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 3b8bd7ca676..a27b7f4c19c 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -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
index 68c93e3d89d..00000000000
--- a/net/dccp/ccids/lib/Makefile
+++ /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
diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c
index 5b3ce0688c5..4d1e4012726 100644
--- a/net/dccp/ccids/lib/loss_interval.c
+++ b/net/dccp/ccids/lib/loss_interval.c
@@ -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)
{
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c
index 6cc108afdc3..b7785b3581e 100644
--- a/net/dccp/ccids/lib/packet_history.c
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -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);
diff --git a/net/dccp/ccids/lib/tfrc.c b/net/dccp/ccids/lib/tfrc.c
index 185916218e0..60c412ccfee 100644
--- a/net/dccp/ccids/lib/tfrc.c
+++ b/net/dccp/ccids/lib/tfrc.c
@@ -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");
diff --git a/net/dccp/ccids/lib/tfrc.h b/net/dccp/ccids/lib/tfrc.h
index ed9857527ac..e9720b14327 100644
--- a/net/dccp/ccids/lib/tfrc.h
+++ b/net/dccp/ccids/lib/tfrc.h
@@ -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_ */
diff --git a/net/dccp/ccids/lib/tfrc_equation.c b/net/dccp/ccids/lib/tfrc_equation.c
index 2f20a29cffe..c5d3a9e5a5a 100644
--- a/net/dccp/ccids/lib/tfrc_equation.c
+++ b/net/dccp/ccids/lib/tfrc_equation.c
@@ -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);
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 0bc4c9a02e1..f2230fc168e 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -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);
}
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index 30f9fb76b92..4152308958a 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -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 */
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 5eb443f656c..7648f316310 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -741,5 +741,3 @@ u32 dccp_sample_rtt(struct sock *sk, long delta)
return delta;
}
-
-EXPORT_SYMBOL_GPL(dccp_sample_rtt);
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 1747ccae8e8..945b4d5d23b 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -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 *
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index f28acf11fc6..35bcddf8a93 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -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)
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index eeeaad2e8b5..40f324655e2 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -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;
}
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 18c486cf498..76f06b94ab9 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -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;
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index af3192d2a5a..eb8a2a0b6eb 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -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;
}
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
index 8f57d4f4328..032f61e9859 100644
--- a/net/iucv/iucv.c
+++ b/net/iucv/iucv.c
@@ -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))
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index 3c94f76d552..3eaa39403c1 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -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,
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 05d178008cb..07372f60bee 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -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;
diff --git a/net/socket.c b/net/socket.c
index 2c730fc718a..06603d73c41 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -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];
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 19245324887..577385a4a5d 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -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:
diff --git a/security/commoncap.c b/security/commoncap.c
index 79713545cd6..69fc9952650 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -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,
diff --git a/security/inode.c b/security/inode.c
index efea5a60546..007ef252dde 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -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:
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index e5520996a75..8f612c8becb 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -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;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 343c8ab14af..c65e4fe4a0f 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -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;
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 1b5551dfc1f..848212fd484 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -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;
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index b20e1cede00..75de40aaab0 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -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"
@@ -37,8 +39,21 @@
#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);
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 0bd4e6bf354..9065ebf9c06 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -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 */
};
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 0dfa0540ce2..bb8d8c766b9 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -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;
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 51848880504..31e44e346dc 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -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 */
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h
index 54615c76802..442e5a82861 100644
--- a/sound/soc/codecs/twl4030.h
+++ b/sound/soc/codecs/twl4030.h
@@ -147,6 +147,13 @@
#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
diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c
index f67579d5276..4935d1bcbd8 100644
--- a/sound/soc/davinci/davinci-sffsdr.c
+++ b/sound/soc/davinci/davinci-sffsdr.c
@@ -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");
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index c670d08e7c9..53b9fb127a6 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -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;
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index b098c0b4c58..f73c1341437 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -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)
{
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 8863eddbac0..6c79ca6df0b 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -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
diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c
index b143ef7152f..a62500e387a 100644
--- a/sound/usb/caiaq/caiaq-device.c
+++ b/sound/usb/caiaq/caiaq-device.c
@@ -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);
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index bbd70d5814a..c709b956322 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -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;
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 6d9f9b135c6..320641ab5be 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -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;
}
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index a49246113e7..00397c8a765 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -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)
diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c
index c2515b680f9..73e59f4403a 100644
--- a/sound/usb/usx2y/us122l.c
+++ b/sound/usb/usx2y/us122l.c
@@ -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;
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
index e5981a63031..ca26c532e77 100644
--- a/sound/usb/usx2y/usbusx2y.c
+++ b/sound/usb/usx2y/usbusx2y.c
@@ -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);