HEAD is gonna to be only 2.6.x oriented.
+++ /dev/null
-#
-# Automatically generated by make menuconfig: don't edit
-#
-CONFIG_X86=y
-CONFIG_ISA=y
-# CONFIG_SBUS is not set
-CONFIG_UID16=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Processor type and features
-#
-CONFIG_LOLAT=y
-# CONFIG_LOLAT_SYSCTL is not set
-# CONFIG_M386 is not set
-# CONFIG_M486 is not set
-# CONFIG_M586 is not set
-# CONFIG_M586TSC is not set
-# CONFIG_M586MMX is not set
-# CONFIG_M686 is not set
-# CONFIG_MPENTIUMIII is not set
-CONFIG_MPENTIUM4=y
-# CONFIG_MK6 is not set
-# CONFIG_MK7 is not set
-# CONFIG_MELAN is not set
-# CONFIG_MCRUSOE is not set
-# CONFIG_MWINCHIPC6 is not set
-# CONFIG_MWINCHIP2 is not set
-# CONFIG_MWINCHIP3D is not set
-# CONFIG_MCYRIXIII is not set
-CONFIG_X86_WP_WORKS_OK=y
-CONFIG_X86_INVLPG=y
-CONFIG_X86_CMPXCHG=y
-CONFIG_X86_XADD=y
-CONFIG_X86_BSWAP=y
-CONFIG_X86_POPAD_OK=y
-# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_X86_L1_CACHE_SHIFT=7
-CONFIG_X86_TSC=y
-CONFIG_X86_GOOD_APIC=y
-CONFIG_X86_PGE=y
-CONFIG_X86_USE_PPRO_CHECKSUM=y
-CONFIG_X86_MCE=y
-# CONFIG_CPU_FREQ is not set
-# CONFIG_TOSHIBA is not set
-# CONFIG_I8K is not set
-CONFIG_MICROCODE=m
-CONFIG_X86_MSR=m
-CONFIG_X86_CPUID=m
-# CONFIG_E820_PROC is not set
-# CONFIG_NOHIGHMEM is not set
-CONFIG_HIGHMEM4G=y
-# CONFIG_HIGHMEM64G is not set
-CONFIG_HIGHMEM=y
-CONFIG_HIGHIO=y
-# CONFIG_MATH_EMULATION is not set
-CONFIG_MTRR=y
-CONFIG_SMP=y
-# CONFIG_MULTIQUAD is not set
-CONFIG_HAVE_DEC_LOCK=y
-
-#
-# General setup
-#
-CONFIG_HZ=100
-CONFIG_NET=y
-CONFIG_X86_IO_APIC=y
-CONFIG_X86_LOCAL_APIC=y
-CONFIG_PCI=y
-# CONFIG_PCI_GOBIOS is not set
-# CONFIG_PCI_GODIRECT is not set
-CONFIG_PCI_GOANY=y
-CONFIG_PCI_BIOS=y
-CONFIG_PCI_DIRECT=y
-CONFIG_PCI_NAMES=y
-
-#
-# Performance-monitoring counters support
-#
-CONFIG_PERFCTR=m
-CONFIG_KPERFCTR=y
-# CONFIG_PERFCTR_DEBUG is not set
-# CONFIG_PERFCTR_INIT_TESTS is not set
-CONFIG_PERFCTR_VIRTUAL=y
-CONFIG_PERFCTR_GLOBAL=y
-# CONFIG_EISA is not set
-# CONFIG_MCA is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
-# CONFIG_HOTPLUG_PCI is not set
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=m
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=m
-# CONFIG_IKCONFIG is not set
-CONFIG_PM=y
-
-#
-# Additional device driver support
-#
-# CONFIG_CIPE is not set
-# CONFIG_CRYPTO_AEP is not set
-# CONFIG_MEGARAC is not set
-CONFIG_FC_QLA2200=m
-CONFIG_FC_QLA2300=m
-# CONFIG_SCSI_ISCSI is not set
-CONFIG_IBMASM=m
-CONFIG_IBMSER=m
-# CONFIG_ACPI is not set
-CONFIG_APM=y
-CONFIG_APM_IGNORE_USER_SUSPEND=y
-# CONFIG_APM_DO_ENABLE is not set
-# CONFIG_APM_CPU_IDLE is not set
-# CONFIG_APM_DISPLAY_BLANK is not set
-CONFIG_APM_RTC_IS_GMT=y
-# CONFIG_APM_ALLOW_INTS is not set
-# CONFIG_APM_REAL_MODE_POWER_OFF is not set
-
-#
-# Binary emulation of other systems
-#
-# CONFIG_ABI is not set
-# CONFIG_ABI_SVR4 is not set
-# CONFIG_BINFMT_COFF is not set
-# CONFIG_BINFMT_XOUT is not set
-# CONFIG_BINFMT_XOUT_X286 is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_PARTITIONS is not set
-# CONFIG_MTD_CONCAT is not set
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-CONFIG_MTD_CHAR=m
-# CONFIG_MTD_BLOCK is not set
-# CONFIG_MTD_BLOCK_RO is not set
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-# CONFIG_MTD_CFI is not set
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_GEN_PROBE=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_NOSWAP=y
-# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-CONFIG_MTD_CFI_GEOMETRY=y
-CONFIG_MTD_CFI_B1=y
-# CONFIG_MTD_CFI_B2 is not set
-# CONFIG_MTD_CFI_B4 is not set
-# CONFIG_MTD_CFI_B8 is not set
-CONFIG_MTD_CFI_I1=y
-# CONFIG_MTD_CFI_I2 is not set
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_AMDSTD=y
-# CONFIG_MTD_RAM is not set
-CONFIG_MTD_ROM=y
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-# CONFIG_MTD_AMDSTD is not set
-# CONFIG_MTD_SHARP is not set
-# CONFIG_MTD_JEDEC is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_PHYSMAP is not set
-# CONFIG_MTD_PNC2000 is not set
-# CONFIG_MTD_SC520CDP is not set
-# CONFIG_MTD_NETSC520 is not set
-# CONFIG_MTD_SBC_GXX is not set
-# CONFIG_MTD_ELAN_104NC is not set
-# CONFIG_MTD_DILNETPC is not set
-# CONFIG_MTD_MIXMEM is not set
-# CONFIG_MTD_OCTAGON is not set
-# CONFIG_MTD_VMAX is not set
-# CONFIG_MTD_L440GX is not set
-# CONFIG_MTD_AMD766ROM is not set
-CONFIG_MTD_ICH2ROM=m
-# CONFIG_MTD_PCI is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-# CONFIG_MTD_DOC1000 is not set
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOCPROBE is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Parallel port support
-#
-CONFIG_PARPORT=m
-CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_CML1=m
-CONFIG_PARPORT_SERIAL=m
-# CONFIG_PARPORT_PC_FIFO is not set
-# CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_AMIGA is not set
-# CONFIG_PARPORT_MFC3 is not set
-# CONFIG_PARPORT_ATARI is not set
-# CONFIG_PARPORT_GSC is not set
-# CONFIG_PARPORT_SUNBPP is not set
-# CONFIG_PARPORT_OTHER is not set
-CONFIG_PARPORT_1284=y
-
-#
-# Plug and Play configuration
-#
-CONFIG_PNP=y
-CONFIG_ISAPNP=y
-# CONFIG_PNPBIOS is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_FD=y
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_CISS_SCSI_TAPE is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_ENBD=m
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-
-#
-# Multi-device support (RAID and LVM)
-#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-CONFIG_BLK_DEV_LVM=m
-
-#
-# Cryptography support (CryptoAPI)
-#
-# CONFIG_CRYPTO is not set
-# CONFIG_CIPHERS is not set
-# CONFIG_CRYPTODEV is not set
-# CONFIG_CRYPTOLOOP is not set
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_FILTER=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_TUX is not set
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_FWMARK=y
-CONFIG_IP_ROUTE_NAT=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_TOS=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_ROUTE_LARGE_TABLES=y
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-CONFIG_SYN_COOKIES=y
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-# CONFIG_IP_NF_FTP is not set
-# CONFIG_IP_NF_IRC is not set
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_KHTTPD=m
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-
-#
-# Appletalk devices
-#
-# CONFIG_DEV_APPLETALK is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-CONFIG_NET_PKTGEN=m
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-# CONFIG_PHONE_IXJ is not set
-# CONFIG_PHONE_IXJ_PCMCIA is not set
-
-#
-# ATA/IDE/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-# CONFIG_BLK_DEV_HD_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_IDEDISK_MULTI_MODE=y
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
-# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
-# CONFIG_BLK_DEV_IDEDISK_IBM is not set
-# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
-# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
-# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
-# CONFIG_BLK_DEV_IDEDISK_WD is not set
-# CONFIG_BLK_DEV_COMMERIAL is not set
-# CONFIG_BLK_DEV_TIVO is not set
-# CONFIG_BLK_DEV_IDECS is not set
-CONFIG_BLK_DEV_IDECD=m
-# CONFIG_BLK_DEV_IDETAPE is not set
-CONFIG_BLK_DEV_IDEFLOPPY=y
-# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-CONFIG_BLK_DEV_ISAPNP=y
-# CONFIG_BLK_DEV_RZ1000 is not set
-CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_IDEPCI_SHARE_IRQ=y
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
-# CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_PCI_WIP is not set
-# CONFIG_BLK_DEV_IDEDMA_TIMEOUT is not set
-# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
-CONFIG_BLK_DEV_ADMA=y
-CONFIG_BLK_DEV_AEC62XX=y
-CONFIG_AEC62XX_TUNING=y
-CONFIG_BLK_DEV_ALI15X3=y
-# CONFIG_WDC_ALI15X3 is not set
-CONFIG_BLK_DEV_AMD74XX=y
-# CONFIG_AMD74XX_OVERRIDE is not set
-CONFIG_BLK_DEV_CMD64X=y
-CONFIG_BLK_DEV_CMD680=y
-CONFIG_BLK_DEV_CY82C693=y
-CONFIG_BLK_DEV_CS5530=y
-CONFIG_BLK_DEV_HPT34X=y
-# CONFIG_HPT34X_AUTODMA is not set
-CONFIG_BLK_DEV_HPT366=y
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_PIIX_TUNING=y
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_ADMA100 is not set
-CONFIG_BLK_DEV_PDC202XX=y
-# CONFIG_PDC202XX_BURST is not set
-# CONFIG_PDC202XX_FORCE is not set
-CONFIG_BLK_DEV_SVWKS=y
-CONFIG_BLK_DEV_SIS5513=y
-CONFIG_BLK_DEV_SLC90E66=y
-# CONFIG_BLK_DEV_TRM290 is not set
-CONFIG_BLK_DEV_VIA82CXXX=y
-CONFIG_BLK_DEV_CENATEK=y
-# CONFIG_IDE_CHIPSETS is not set
-# CONFIG_BLK_DEV_ELEVATOR_NOOP is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_DMA_NONPCI is not set
-CONFIG_BLK_DEV_IDE_MODES=y
-# CONFIG_BLK_DEV_ATARAID is not set
-# CONFIG_BLK_DEV_ATARAID_PDC is not set
-# CONFIG_BLK_DEV_ATARAID_HPT is not set
-
-#
-# SCSI support
-#
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SD_EXTRA_DEVS=40
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=m
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_SR_EXTRA_DEVS=4
-CONFIG_CHR_DEV_SG=m
-# CONFIG_SCSI_DEBUG_QUEUES is not set
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AHA1740 is not set
-# CONFIG_SCSI_AACRAID is not set
-CONFIG_SCSI_AIC7XXX=y
-CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
-CONFIG_AIC7XXX_RESET_DELAY_MS=15000
-# CONFIG_AIC7XXX_PROBE_EISA_VL is not set
-# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_AM53C974 is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_DMA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_PPA is not set
-# CONFIG_SCSI_IMM is not set
-# CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_NCR53C7xx is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_NCR53C8XX is not set
-# CONFIG_SCSI_SYM53C8XX is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_NEWISP is not set
-# CONFIG_SCSI_SEAGATE is not set
-# CONFIG_SCSI_SIM710 is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_ULTRASTOR is not set
-CONFIG_SCSI_DEBUG=m
-
-#
-# Fusion MPT device support
-#
-CONFIG_FUSION=y
-CONFIG_FUSION_BOOT=y
-CONFIG_FUSION_ISENSE=m
-CONFIG_FUSION_CTL=m
-# CONFIG_FUSION_LAN is not set
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-# CONFIG_I2O_PCI is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-CONFIG_DUMMY=m
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-# CONFIG_NET_SB1000 is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_SUNLANCE is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNBMAC is not set
-# CONFIG_SUNQE is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
-# CONFIG_CS89x0 is not set
-CONFIG_TULIP=m
-# CONFIG_TC35815 is not set
-# CONFIG_TULIP_MWI is not set
-CONFIG_TULIP_MMIO=y
-CONFIG_DE4X5=m
-# CONFIG_DGRS is not set
-# CONFIG_DM9102 is not set
-CONFIG_EEPRO100=m
-CONFIG_NET_E100=m
-# CONFIG_LNE390 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_NE3210 is not set
-# CONFIG_ES3210 is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_8139TOO_PIO is not set
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-# CONFIG_8139TOO_8129 is not set
-# CONFIG_8139_NEW_RX_RESET is not set
-# CONFIG_SIS900 is not set
-# CONFIG_SIS900_OLD is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_RHINE_MMIO is not set
-# CONFIG_WINBOND_840 is not set
-# CONFIG_NET_POCKET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-CONFIG_ACENIC=m
-# CONFIG_ACENIC_OMIT_TIGON_I is not set
-# CONFIG_DL2K is not set
-# CONFIG_MYRI_SBUS is not set
-CONFIG_NS83820=m
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_SK98LIN is not set
-CONFIG_NET_BROADCOM=m
-CONFIG_TIGON3=m
-CONFIG_NET_E1000=m
-# CONFIG_FDDI is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Quadrics Supercomputers
-#
-
-#
-# QsNet
-#
-CONFIG_QUADRICS=y
-CONFIG_QSNETMOD=m
-CONFIG_ELAN3MOD=m
-CONFIG_EPMOD=m
-CONFIG_EIPMOD=m
-CONFIG_RMSMOD=m
-CONFIG_JTAG=m
-
-#
-# QsNet II
-#
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-CONFIG_KALLSYMS=y
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Input core support
-#
-# CONFIG_INPUT is not set
-# CONFIG_INPUT_KEYBDEV is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-
-#
-# Character devices
-#
-CONFIG_ECC=m
-CONFIG_CHAOSTEST=m
-CONFIG_P4THERM=m
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-CONFIG_SERIAL_EXTENDED=y
-# CONFIG_SERIAL_MANY_PORTS is not set
-CONFIG_SERIAL_SHARE_IRQ=y
-# CONFIG_SERIAL_DETECT_IRQ is not set
-# CONFIG_SERIAL_MULTIPORT is not set
-# CONFIG_HUB6 is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=2048
-# CONFIG_PRINTER is not set
-# CONFIG_PPDEV is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-CONFIG_I2C_MAINBOARD=y
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_HYDRA is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_TSUNAMI is not set
-CONFIG_I2C_I801=m
-# CONFIG_I2C_I810 is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-# CONFIG_I2C_VOODOO3 is not set
-CONFIG_I2C_ISA=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_PROC=y
-
-#
-# Hardware sensors support
-#
-CONFIG_SENSORS=y
-CONFIG_SENSORS_ADM1021=m
-# CONFIG_SENSORS_ADM1024 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_FSCSCY is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_MAXILIFE is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_MTP008 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-CONFIG_SENSORS_LM87=m
-# CONFIG_SENSORS_SIS5595 is not set
-# CONFIG_SENSORS_THMC50 is not set
-# CONFIG_SENSORS_VIA686A is not set
-CONFIG_SENSORS_W83781D=y
-# CONFIG_SENSORS_OTHER is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-CONFIG_MOUSE=y
-CONFIG_PSMOUSE=y
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
-# CONFIG_MK712_MOUSE is not set
-
-#
-# Joysticks
-#
-# CONFIG_INPUT_GAMEPORT is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_AMD_RNG is not set
-# CONFIG_INTEL_RNG is not set
-# CONFIG_AMD_PM768 is not set
-# CONFIG_NVRAM is not set
-CONFIG_RTC=y
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_SONYPI is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-CONFIG_AGP=m
-CONFIG_AGP_INTEL=y
-# CONFIG_AGP_I810 is not set
-# CONFIG_AGP_VIA is not set
-# CONFIG_AGP_AMD is not set
-# CONFIG_AGP_SIS is not set
-# CONFIG_AGP_ALI is not set
-# CONFIG_AGP_SWORKS is not set
-# CONFIG_DRM is not set
-# CONFIG_MWAVE is not set
-# CONFIG_BATTERY_GERICOM is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Crypto Hardware support
-#
-# CONFIG_CRYPTO is not set
-
-#
-# File systems
-#
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_ADFS_FS_RW is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BEFS_DEBUG is not set
-# CONFIG_BFS_FS is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXTN_FS=m
-CONFIG_JBD=y
-CONFIG_JBD_DEBUG=y
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_UMSDOS_FS=m
-CONFIG_VFAT_FS=m
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-CONFIG_CRAMFS=y
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-# CONFIG_JFS_FS is not set
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_RW is not set
-# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-CONFIG_ROMFS_FS=m
-CONFIG_EXT2_FS=y
-# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
-# CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
-
-#
-# Network File Systems
-#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-CONFIG_NFS_FS=m
-CONFIG_NFS_V3=y
-# CONFIG_ROOT_NFS is not set
-CONFIG_NFSD=m
-CONFIG_NFSD_V3=y
-CONFIG_NFSD_TCP=y
-CONFIG_SUNRPC=m
-CONFIG_LOCKD=m
-CONFIG_LOCKD_V4=y
-# CONFIG_SMB_FS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
-# CONFIG_PFS_FS is not set
-CONFIG_ZISOFS_FS=y
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-CONFIG_OSF_PARTITION=y
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
-CONFIG_BSD_DISKLABEL=y
-CONFIG_MINIX_SUBPARTITION=y
-CONFIG_SOLARIS_X86_PARTITION=y
-CONFIG_UNIXWARE_DISKLABEL=y
-# CONFIG_LDM_PARTITION is not set
-CONFIG_SGI_PARTITION=y
-# CONFIG_ULTRIX_PARTITION is not set
-CONFIG_SUN_PARTITION=y
-# CONFIG_SMB_NLS is not set
-CONFIG_NLS=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-CONFIG_NLS_CODEPAGE_850=m
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-CONFIG_NLS_ISO8859_1=m
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Console drivers
-#
-CONFIG_VGA_CONSOLE=y
-CONFIG_VIDEO_SELECT=y
-# CONFIG_VIDEO_IGNORE_BAD_MODE is not set
-# CONFIG_MDA_CONSOLE is not set
-
-#
-# Frame-buffer support
-#
-# CONFIG_FB is not set
-# CONFIG_SPEAKUP is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BLUEZ is not set
-
-#
-# Kernel hacking
-#
-CONFIG_DEBUG_KERNEL=y
-CONFIG_FRAME_POINTER=y
-CONFIG_STACK_TRACE_SCAN=y
-CONFIG_STACK_TRACE_FPTR=y
-CONFIG_STACK_TRACE_PARAM_COUNT=4
-# CONFIG_DEBUG_HIGHMEM is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_IOVIRT is not set
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_MCL_COREDUMP=y
-CONFIG_BOOTIMG=y
-# CONFIG_OPROFILE is not set
-
-#
-# Library routines
-#
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
+++ /dev/null
-#
-# Automatically generated by make menuconfig: don't edit
-#
-CONFIG_X86=y
-# CONFIG_SBUS is not set
-CONFIG_UID16=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Processor type and features
-#
-CONFIG_LOLAT=y
-# CONFIG_M386 is not set
-# CONFIG_M486 is not set
-# CONFIG_M586 is not set
-# CONFIG_M586TSC is not set
-# CONFIG_M586MMX is not set
-CONFIG_M686=y
-# CONFIG_MPENTIUMIII is not set
-# CONFIG_MPENTIUM4 is not set
-# CONFIG_MK6 is not set
-# CONFIG_MK7 is not set
-# CONFIG_MELAN is not set
-# CONFIG_MCRUSOE is not set
-# CONFIG_MWINCHIPC6 is not set
-# CONFIG_MWINCHIP2 is not set
-# CONFIG_MWINCHIP3D is not set
-# CONFIG_MCYRIXIII is not set
-CONFIG_X86_WP_WORKS_OK=y
-CONFIG_X86_INVLPG=y
-CONFIG_X86_CMPXCHG=y
-CONFIG_X86_XADD=y
-CONFIG_X86_BSWAP=y
-CONFIG_X86_POPAD_OK=y
-# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_X86_L1_CACHE_SHIFT=7
-CONFIG_X86_HAS_TSC=y
-CONFIG_X86_GOOD_APIC=y
-CONFIG_X86_PGE=y
-CONFIG_X86_USE_PPRO_CHECKSUM=y
-CONFIG_X86_PPRO_FENCE=y
-CONFIG_X86_F00F_WORKS_OK=y
-CONFIG_X86_MCE=y
-
-#
-# CPU Frequency scaling
-#
-CONFIG_CPU_FREQ=y
-# CONFIG_CPU_FREQ_24_API is not set
-CONFIG_X86_POWERNOW_K6=m
-# CONFIG_X86_LONGHAUL is not set
-CONFIG_X86_SPEEDSTEP=m
-# CONFIG_X86_P4_CLOCKMOD is not set
-# CONFIG_X86_LONGRUN is not set
-CONFIG_TOSHIBA=m
-CONFIG_I8K=m
-CONFIG_MICROCODE=m
-CONFIG_X86_MSR=m
-CONFIG_X86_CPUID=m
-# CONFIG_E820_PROC is not set
-CONFIG_EDD=m
-# CONFIG_NOHIGHMEM is not set
-CONFIG_HIGHMEM4G=y
-# CONFIG_HIGHMEM64G is not set
-CONFIG_HIGHMEM=y
-CONFIG_HIGHPTE=y
-CONFIG_HIGHIO=y
-# CONFIG_MATH_EMULATION is not set
-CONFIG_MTRR=y
-# CONFIG_SMP is not set
-CONFIG_X86_UP_APIC=y
-CONFIG_X86_UP_IOAPIC=y
-CONFIG_X86_LOCAL_APIC=y
-CONFIG_X86_IO_APIC=y
-# CONFIG_X86_TSC_DISABLE is not set
-CONFIG_X86_TSC=y
-
-#
-# General setup
-#
-CONFIG_NET=y
-CONFIG_PCI=y
-# CONFIG_PCI_GOBIOS is not set
-# CONFIG_PCI_GODIRECT is not set
-CONFIG_PCI_GOANY=y
-CONFIG_PCI_BIOS=y
-CONFIG_PCI_DIRECT=y
-CONFIG_ISA=y
-CONFIG_PCI_NAMES=y
-CONFIG_EISA=y
-# CONFIG_MCA is not set
-CONFIG_HOTPLUG=y
-
-#
-# PCMCIA/CardBus support
-#
-CONFIG_PCMCIA=m
-CONFIG_CARDBUS=y
-CONFIG_TCIC=y
-CONFIG_I82092=y
-CONFIG_I82365=y
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-# CONFIG_HOTPLUG_PCI_ACPI is not set
-# CONFIG_HOTPLUG_PCI_COMPAQ is not set
-# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
-# CONFIG_HOTPLUG_PCI_IBM is not set
-# CONFIG_HOTPLUG_PCI_H2999 is not set
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=m
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=m
-CONFIG_PM=y
-# CONFIG_ACPI is not set
-CONFIG_APM=y
-# CONFIG_APM_IGNORE_USER_SUSPEND is not set
-# CONFIG_APM_DO_ENABLE is not set
-CONFIG_APM_CPU_IDLE=y
-# CONFIG_APM_DISPLAY_BLANK is not set
-CONFIG_APM_RTC_IS_GMT=y
-# CONFIG_APM_ALLOW_INTS is not set
-# CONFIG_APM_REAL_MODE_POWER_OFF is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-CONFIG_PARPORT=m
-CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_CML1=m
-CONFIG_PARPORT_SERIAL=m
-# CONFIG_PARPORT_PC_FIFO is not set
-# CONFIG_PARPORT_PC_SUPERIO is not set
-CONFIG_PARPORT_PC_PCMCIA=m
-# CONFIG_PARPORT_AMIGA is not set
-# CONFIG_PARPORT_MFC3 is not set
-# CONFIG_PARPORT_ATARI is not set
-# CONFIG_PARPORT_GSC is not set
-# CONFIG_PARPORT_SUNBPP is not set
-# CONFIG_PARPORT_OTHER is not set
-CONFIG_PARPORT_1284=y
-
-#
-# Plug and Play configuration
-#
-CONFIG_PNP=y
-CONFIG_ISAPNP=y
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_FD=y
-CONFIG_BLK_DEV_XD=m
-CONFIG_PARIDE=m
-CONFIG_PARIDE_PARPORT=m
-CONFIG_PARIDE_PD=m
-CONFIG_PARIDE_PCD=m
-CONFIG_PARIDE_PF=m
-CONFIG_PARIDE_PT=m
-CONFIG_PARIDE_PG=m
-CONFIG_PARIDE_ATEN=m
-CONFIG_PARIDE_BPCK=m
-CONFIG_PARIDE_BPCK6=m
-CONFIG_PARIDE_COMM=m
-CONFIG_PARIDE_DSTR=m
-CONFIG_PARIDE_FIT2=m
-CONFIG_PARIDE_FIT3=m
-CONFIG_PARIDE_EPAT=m
-CONFIG_PARIDE_EPATC8=y
-CONFIG_PARIDE_EPIA=m
-CONFIG_PARIDE_FRIQ=m
-CONFIG_PARIDE_FRPW=m
-CONFIG_PARIDE_KBIC=m
-CONFIG_PARIDE_KTTI=m
-CONFIG_PARIDE_ON20=m
-CONFIG_PARIDE_ON26=m
-CONFIG_BLK_CPQ_DA=m
-CONFIG_BLK_CPQ_CISS_DA=m
-CONFIG_CISS_SCSI_TAPE=y
-CONFIG_BLK_DEV_DAC960=m
-CONFIG_BLK_DEV_UMEM=m
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_BLK_STATS=y
-
-#
-# Multi-device support (RAID and LVM)
-#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=m
-CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_RAID5=m
-CONFIG_MD_MULTIPATH=m
-CONFIG_BLK_DEV_LVM=m
-
-#
-# Cryptography support (CryptoAPI)
-#
-CONFIG_CRYPTO=m
-CONFIG_CIPHERS=m
-CONFIG_CIPHER_AES=m
-CONFIG_CIPHER_IDENTITY=m
-CONFIG_CRYPTODEV=m
-CONFIG_CRYPTOLOOP=m
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_FILTER=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_TUX=m
-CONFIG_TUX_EXTCGI=y
-# CONFIG_TUX_EXTENDED_LOG is not set
-# CONFIG_TUX_DEBUG is not set
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_FWMARK=y
-CONFIG_IP_ROUTE_NAT=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_TOS=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_ROUTE_LARGE_TABLES=y
-# CONFIG_IP_PNP is not set
-CONFIG_NET_IPIP=m
-CONFIG_NET_IPGRE=m
-CONFIG_NET_IPGRE_BROADCAST=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-CONFIG_SYN_COOKIES=y
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_UNCLEAN=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_MIRROR=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_NAT_LOCAL=y
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_COMPAT_IPFWADM=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IPV6=m
-
-#
-# IPv6: Netfilter Configuration
-#
-# CONFIG_IP6_NF_QUEUE is not set
-CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_LIMIT=m
-CONFIG_IP6_NF_MATCH_MAC=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
-CONFIG_IP6_NF_MATCH_OWNER=m
-CONFIG_IP6_NF_MATCH_MARK=m
-CONFIG_IP6_NF_MATCH_LENGTH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=m
-CONFIG_IP6_NF_TARGET_LOG=m
-CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_MARK=m
-# CONFIG_KHTTPD is not set
-CONFIG_ATM=y
-CONFIG_ATM_CLIP=y
-# CONFIG_ATM_CLIP_NO_ICMP is not set
-CONFIG_ATM_LANE=m
-CONFIG_ATM_MPOA=m
-CONFIG_ATM_BR2684=m
-CONFIG_ATM_BR2684_IPFILTER=y
-CONFIG_VLAN_8021Q=m
-CONFIG_IPX=m
-# CONFIG_IPX_INTERN is not set
-CONFIG_ATALK=m
-
-#
-# Appletalk devices
-#
-CONFIG_DEV_APPLETALK=y
-CONFIG_LTPC=m
-CONFIG_COPS=m
-CONFIG_COPS_DAYNA=y
-CONFIG_COPS_TANGENT=y
-CONFIG_IPDDP=m
-CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
-CONFIG_DECNET=m
-CONFIG_DECNET_SIOCGIFCONF=y
-CONFIG_DECNET_ROUTER=y
-CONFIG_DECNET_ROUTE_FWMARK=y
-CONFIG_BRIDGE=m
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
-CONFIG_NET_DIVERT=y
-# CONFIG_ECONET is not set
-CONFIG_WAN_ROUTER=m
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_CBQ=m
-CONFIG_NET_SCH_HTB=m
-CONFIG_NET_SCH_CSZ=m
-# CONFIG_NET_SCH_ATM is not set
-CONFIG_NET_SCH_PRIO=m
-CONFIG_NET_SCH_RED=m
-CONFIG_NET_SCH_SFQ=m
-CONFIG_NET_SCH_TEQL=m
-CONFIG_NET_SCH_TBF=m
-CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DSMARK=m
-CONFIG_NET_SCH_INGRESS=m
-CONFIG_NET_QOS=y
-CONFIG_NET_ESTIMATOR=y
-CONFIG_NET_CLS=y
-CONFIG_NET_CLS_TCINDEX=m
-CONFIG_NET_CLS_ROUTE4=m
-CONFIG_NET_CLS_ROUTE=y
-CONFIG_NET_CLS_FW=m
-CONFIG_NET_CLS_U32=m
-CONFIG_NET_CLS_RSVP=m
-CONFIG_NET_CLS_RSVP6=m
-CONFIG_NET_CLS_POLICE=y
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-
-#
-# Telephony Support
-#
-CONFIG_PHONE=m
-CONFIG_PHONE_IXJ=m
-CONFIG_PHONE_IXJ_PCMCIA=m
-
-#
-# ATA/IDE/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-# CONFIG_BLK_DEV_HD_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_IDEDISK_MULTI_MODE=y
-# CONFIG_IDEDISK_STROKE is not set
-CONFIG_BLK_DEV_IDECS=m
-CONFIG_BLK_DEV_IDECD=m
-CONFIG_BLK_DEV_IDETAPE=m
-CONFIG_BLK_DEV_IDEFLOPPY=y
-CONFIG_BLK_DEV_IDESCSI=m
-# CONFIG_IDE_TASK_IOCTL is not set
-CONFIG_BLK_DEV_CMD640=y
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-CONFIG_BLK_DEV_ISAPNP=y
-CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_IDEPCI_SHARE_IRQ=y
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
-# CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_PCI_WIP is not set
-CONFIG_BLK_DEV_ADMA=y
-CONFIG_BLK_DEV_AEC62XX=y
-CONFIG_BLK_DEV_ALI15X3=y
-# CONFIG_WDC_ALI15X3 is not set
-CONFIG_BLK_DEV_AMD74XX=y
-# CONFIG_AMD74XX_OVERRIDE is not set
-CONFIG_BLK_DEV_CMD64X=y
-CONFIG_BLK_DEV_TRIFLEX=y
-CONFIG_BLK_DEV_CY82C693=y
-CONFIG_BLK_DEV_CS5530=y
-CONFIG_BLK_DEV_HPT34X=y
-# CONFIG_HPT34X_AUTODMA is not set
-CONFIG_BLK_DEV_HPT366=y
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_BLK_DEV_NFORCE=y
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_PDC202XX_OLD=y
-# CONFIG_PDC202XX_BURST is not set
-CONFIG_BLK_DEV_PDC202XX_NEW=y
-CONFIG_PDC202XX_FORCE=y
-CONFIG_BLK_DEV_RZ1000=y
-# CONFIG_BLK_DEV_SC1200 is not set
-CONFIG_BLK_DEV_SVWKS=y
-CONFIG_BLK_DEV_SIIMAGE=y
-CONFIG_BLK_DEV_SIS5513=y
-CONFIG_BLK_DEV_SLC90E66=y
-# CONFIG_BLK_DEV_TRM290 is not set
-CONFIG_BLK_DEV_VIA82CXXX=y
-# CONFIG_IDE_CHIPSETS is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_DMA_NONPCI is not set
-CONFIG_BLK_DEV_PDC202XX=y
-CONFIG_BLK_DEV_IDE_MODES=y
-CONFIG_BLK_DEV_ATARAID=m
-CONFIG_BLK_DEV_ATARAID_PDC=m
-CONFIG_BLK_DEV_ATARAID_HPT=m
-CONFIG_BLK_DEV_ATARAID_SII=m
-
-#
-# SCSI support
-#
-CONFIG_SCSI=m
-CONFIG_BLK_DEV_SD=m
-CONFIG_SD_EXTRA_DEVS=40
-CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
-CONFIG_BLK_DEV_SR=m
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_SR_EXTRA_DEVS=4
-CONFIG_CHR_DEV_SG=m
-# CONFIG_SCSI_DEBUG_QUEUES is not set
-# CONFIG_SCSI_MULTI_LUN is not set
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-
-#
-# SCSI low-level drivers
-#
-CONFIG_BLK_DEV_3W_XXXX_RAID=m
-CONFIG_SCSI_7000FASST=m
-CONFIG_SCSI_ACARD=m
-CONFIG_SCSI_AHA152X=m
-CONFIG_SCSI_AHA1542=m
-CONFIG_SCSI_AHA1740=m
-CONFIG_SCSI_AACRAID=m
-CONFIG_SCSI_AIC7XXX=m
-CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
-CONFIG_AIC7XXX_RESET_DELAY_MS=15000
-# CONFIG_AIC7XXX_PROBE_EISA_VL is not set
-# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
-CONFIG_SCSI_AIC79XX=m
-CONFIG_AIC79XX_CMDS_PER_DEVICE=253
-CONFIG_AIC79XX_RESET_DELAY_MS=15000
-# CONFIG_AIC79XX_BUILD_FIRMWARE is not set
-CONFIG_AIC79XX_ENABLE_RD_STRM=y
-# CONFIG_AIC79XX_DEBUG_ENABLE is not set
-CONFIG_AIC79XX_DEBUG_MASK=0
-CONFIG_SCSI_AIC7XXX_OLD=m
-CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y
-CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=32
-CONFIG_AIC7XXX_OLD_PROC_STATS=y
-CONFIG_SCSI_DPT_I2O=m
-CONFIG_SCSI_ADVANSYS=m
-CONFIG_SCSI_IN2000=m
-CONFIG_SCSI_AM53C974=m
-CONFIG_SCSI_MEGARAID=m
-CONFIG_SCSI_BUSLOGIC=m
-# CONFIG_SCSI_OMIT_FLASHPOINT is not set
-CONFIG_SCSI_CPQFCTS=m
-CONFIG_SCSI_DMX3191D=m
-CONFIG_SCSI_DTC3280=m
-CONFIG_SCSI_EATA=m
-CONFIG_SCSI_EATA_TAGGED_QUEUE=y
-# CONFIG_SCSI_EATA_LINKED_COMMANDS is not set
-CONFIG_SCSI_EATA_MAX_TAGS=16
-CONFIG_SCSI_EATA_DMA=m
-CONFIG_SCSI_EATA_PIO=m
-CONFIG_SCSI_FUTURE_DOMAIN=m
-CONFIG_SCSI_GDTH=m
-CONFIG_SCSI_GENERIC_NCR5380=m
-# CONFIG_SCSI_GENERIC_NCR53C400 is not set
-CONFIG_SCSI_G_NCR5380_PORT=y
-# CONFIG_SCSI_G_NCR5380_MEM is not set
-CONFIG_SCSI_IPS=m
-CONFIG_SCSI_INITIO=m
-CONFIG_SCSI_INIA100=m
-CONFIG_SCSI_PPA=m
-CONFIG_SCSI_IMM=m
-# CONFIG_SCSI_IZIP_EPP16 is not set
-# CONFIG_SCSI_IZIP_SLOW_CTR is not set
-CONFIG_SCSI_NCR53C406A=m
-CONFIG_SCSI_NCR53C7xx=m
-# CONFIG_SCSI_NCR53C7xx_sync is not set
-CONFIG_SCSI_NCR53C7xx_FAST=y
-CONFIG_SCSI_NCR53C7xx_DISCONNECT=y
-CONFIG_SCSI_SYM53C8XX_2=m
-CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
-CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
-CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
-CONFIG_SCSI_NCR53C8XX=m
-CONFIG_SCSI_SYM53C8XX=m
-CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
-CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
-CONFIG_SCSI_NCR53C8XX_SYNC=40
-# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
-# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set
-# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
-CONFIG_SCSI_PAS16=m
-CONFIG_SCSI_PCI2000=m
-CONFIG_SCSI_PCI2220I=m
-CONFIG_SCSI_PSI240I=m
-CONFIG_SCSI_QLOGIC_FAS=m
-CONFIG_SCSI_QLOGIC_ISP=m
-CONFIG_SCSI_QLOGIC_FC=m
-# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
-CONFIG_SCSI_QLOGIC_1280=m
-CONFIG_SCSI_NEWISP=m
-CONFIG_SCSI_SEAGATE=m
-CONFIG_SCSI_SIM710=m
-CONFIG_SCSI_SYM53C416=m
-CONFIG_SCSI_DC390T=m
-# CONFIG_SCSI_DC390T_NOGENSUPP is not set
-CONFIG_SCSI_T128=m
-CONFIG_SCSI_U14_34F=m
-# CONFIG_SCSI_U14_34F_LINKED_COMMANDS is not set
-CONFIG_SCSI_U14_34F_MAX_TAGS=8
-CONFIG_SCSI_ULTRASTOR=m
-CONFIG_SCSI_NSP32=m
-CONFIG_SCSI_DEBUG=m
-
-#
-# PCMCIA SCSI adapter support
-#
-CONFIG_SCSI_PCMCIA=y
-CONFIG_PCMCIA_AHA152X=m
-CONFIG_PCMCIA_FDOMAIN=m
-CONFIG_PCMCIA_NINJA_SCSI=m
-CONFIG_PCMCIA_QLOGIC=m
-
-#
-# Fusion MPT device support
-#
-CONFIG_FUSION=m
-# CONFIG_FUSION_BOOT is not set
-CONFIG_FUSION_MAX_SGE=40
-# CONFIG_FUSION_ISENSE is not set
-CONFIG_FUSION_CTL=m
-CONFIG_FUSION_LAN=m
-CONFIG_NET_FC=y
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-CONFIG_IEEE1394=m
-# CONFIG_IEEE1394_PCILYNX is not set
-CONFIG_IEEE1394_OHCI1394=m
-CONFIG_IEEE1394_VIDEO1394=m
-CONFIG_IEEE1394_SBP2=m
-CONFIG_IEEE1394_SBP2_PHYS_DMA=y
-CONFIG_IEEE1394_ETH1394=m
-CONFIG_IEEE1394_DV1394=m
-CONFIG_IEEE1394_RAWIO=m
-CONFIG_IEEE1394_CMP=m
-CONFIG_IEEE1394_AMDTP=m
-# CONFIG_IEEE1394_VERBOSEDEBUG is not set
-
-#
-# I2O device support
-#
-CONFIG_I2O=m
-CONFIG_I2O_PCI=m
-CONFIG_I2O_BLOCK=m
-CONFIG_I2O_LAN=m
-CONFIG_I2O_SCSI=m
-CONFIG_I2O_PROC=m
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-CONFIG_DUMMY=m
-CONFIG_BONDING=m
-CONFIG_EQUALIZER=m
-CONFIG_TUN=m
-CONFIG_ETHERTAP=m
-CONFIG_NET_SB1000=m
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_SUNLANCE is not set
-CONFIG_HAPPYMEAL=m
-# CONFIG_SUNBMAC is not set
-# CONFIG_SUNQE is not set
-CONFIG_SUNGEM=m
-CONFIG_NET_VENDOR_3COM=y
-CONFIG_EL1=m
-CONFIG_EL2=m
-CONFIG_ELPLUS=m
-CONFIG_EL16=m
-CONFIG_EL3=m
-CONFIG_3C515=m
-# CONFIG_ELMC is not set
-# CONFIG_ELMC_II is not set
-CONFIG_VORTEX=m
-CONFIG_LANCE=m
-CONFIG_NET_VENDOR_SMC=y
-CONFIG_WD80x3=m
-# CONFIG_ULTRAMCA is not set
-CONFIG_ULTRA=m
-CONFIG_ULTRA32=m
-CONFIG_SMC9194=m
-CONFIG_NET_VENDOR_RACAL=y
-CONFIG_NI5010=m
-CONFIG_NI52=m
-CONFIG_NI65=m
-CONFIG_AT1700=m
-CONFIG_DEPCA=m
-CONFIG_HP100=m
-CONFIG_NET_ISA=y
-CONFIG_E2100=m
-CONFIG_EWRK3=m
-CONFIG_EEXPRESS=m
-CONFIG_EEXPRESS_PRO=m
-CONFIG_HPLAN_PLUS=m
-CONFIG_HPLAN=m
-CONFIG_LP486E=m
-CONFIG_ETH16I=m
-CONFIG_NE2000=m
-CONFIG_NET_PCI=y
-CONFIG_PCNET32=m
-CONFIG_AMD8111_ETH=m
-CONFIG_ADAPTEC_STARFIRE=m
-CONFIG_AC3200=m
-CONFIG_APRICOT=m
-CONFIG_CS89x0=m
-CONFIG_TULIP=m
-# CONFIG_TULIP_MWI is not set
-CONFIG_TULIP_MMIO=y
-CONFIG_DE4X5=m
-CONFIG_DGRS=m
-CONFIG_DM9102=m
-CONFIG_EEPRO100=m
-CONFIG_E100=m
-CONFIG_LNE390=m
-CONFIG_FEALNX=m
-CONFIG_NATSEMI=m
-CONFIG_NE2K_PCI=m
-CONFIG_NE3210=m
-CONFIG_ES3210=m
-CONFIG_8139CP=m
-CONFIG_8139TOO=m
-# CONFIG_8139TOO_PIO is not set
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-CONFIG_8139TOO_8129=y
-# CONFIG_8139_OLD_RX_RESET is not set
-CONFIG_SIS900=m
-CONFIG_EPIC100=m
-CONFIG_SUNDANCE=m
-CONFIG_SUNDANCE_MMIO=y
-CONFIG_TLAN=m
-CONFIG_TC35815=m
-CONFIG_VIA_RHINE=m
-# CONFIG_VIA_RHINE_MMIO is not set
-CONFIG_WINBOND_840=m
-CONFIG_NET_POCKET=y
-CONFIG_ATP=m
-CONFIG_DE600=m
-CONFIG_DE620=m
-
-#
-# Ethernet (1000 Mbit)
-#
-CONFIG_ACENIC=m
-# CONFIG_ACENIC_OMIT_TIGON_I is not set
-CONFIG_DL2K=m
-CONFIG_E1000=m
-# CONFIG_MYRI_SBUS is not set
-CONFIG_NS83820=m
-CONFIG_HAMACHI=m
-CONFIG_YELLOWFIN=m
-CONFIG_R8169=m
-CONFIG_SK98LIN=m
-CONFIG_TIGON3=m
-CONFIG_FDDI=y
-CONFIG_DEFXX=m
-CONFIG_SKFP=m
-CONFIG_NETCONSOLE=m
-# CONFIG_HIPPI is not set
-CONFIG_PLIP=m
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-# CONFIG_PPP_BSDCOMP is not set
-# CONFIG_PPPOE is not set
-CONFIG_PPPOATM=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-CONFIG_SLIP_MODE_SLIP6=y
-
-#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-CONFIG_STRIP=m
-CONFIG_WAVELAN=m
-CONFIG_ARLAN=m
-CONFIG_AIRONET4500=m
-CONFIG_AIRONET4500_NONCS=m
-CONFIG_AIRONET4500_PNP=y
-CONFIG_AIRONET4500_PCI=y
-CONFIG_AIRONET4500_ISA=y
-CONFIG_AIRONET4500_I365=y
-CONFIG_AIRONET4500_PROC=m
-CONFIG_AIRO=m
-CONFIG_HERMES=m
-CONFIG_PLX_HERMES=m
-CONFIG_PCI_HERMES=m
-CONFIG_PCMCIA_HERMES=m
-CONFIG_AIRO_CS=m
-CONFIG_NET_WIRELESS=y
-CONFIG_PCMCIA_HERMES_OLD=m
-
-#
-# Token Ring devices
-#
-CONFIG_TR=y
-CONFIG_IBMTR=m
-CONFIG_IBMOL=m
-CONFIG_IBMLS=m
-CONFIG_3C359=m
-CONFIG_TMS380TR=m
-CONFIG_TMSPCI=m
-CONFIG_TMSISA=m
-CONFIG_ABYSS=m
-# CONFIG_MADGEMC is not set
-CONFIG_SMCTR=m
-CONFIG_NET_FC=y
-CONFIG_IPHASE5526=m
-CONFIG_RCPCI=m
-CONFIG_SHAPER=m
-
-#
-# Wan interfaces
-#
-CONFIG_WAN=y
-CONFIG_HOSTESS_SV11=m
-CONFIG_COSA=m
-# CONFIG_COMX is not set
-# CONFIG_DSCC4 is not set
-# CONFIG_LANMEDIA is not set
-CONFIG_ATI_XX20=m
-CONFIG_SEALEVEL_4021=m
-# CONFIG_SYNCLINK_SYNCPPP is not set
-# CONFIG_HDLC is not set
-CONFIG_DLCI=m
-CONFIG_DLCI_COUNT=24
-CONFIG_DLCI_MAX=8
-CONFIG_SDLA=m
-CONFIG_WAN_ROUTER_DRIVERS=y
-CONFIG_VENDOR_SANGOMA=m
-CONFIG_WANPIPE_CHDLC=y
-CONFIG_WANPIPE_FR=y
-CONFIG_WANPIPE_X25=y
-CONFIG_WANPIPE_PPP=y
-CONFIG_WANPIPE_MULTPPP=y
-CONFIG_CYCLADES_SYNC=m
-CONFIG_CYCLOMX_X25=y
-# CONFIG_LAPBETHER is not set
-# CONFIG_X25_ASY is not set
-CONFIG_SBNI=m
-CONFIG_SBNI_MULTILINE=y
-
-#
-# PCMCIA network device support
-#
-CONFIG_NET_PCMCIA=y
-CONFIG_PCMCIA_3C589=m
-CONFIG_PCMCIA_3C574=m
-CONFIG_PCMCIA_FMVJ18X=m
-CONFIG_PCMCIA_PCNET=m
-CONFIG_PCMCIA_AXNET=m
-CONFIG_PCMCIA_NMCLAN=m
-CONFIG_PCMCIA_SMC91C92=m
-CONFIG_PCMCIA_XIRC2PS=m
-# CONFIG_ARCNET_COM20020_CS is not set
-CONFIG_PCMCIA_IBMTR=m
-CONFIG_PCMCIA_XIRCOM=m
-CONFIG_PCMCIA_XIRTULIP=m
-CONFIG_NET_PCMCIA_RADIO=y
-CONFIG_PCMCIA_RAYCS=m
-CONFIG_PCMCIA_NETWAVE=m
-CONFIG_PCMCIA_WAVELAN=m
-CONFIG_PCMCIA_WVLAN=m
-CONFIG_AIRONET4500_CS=m
-
-#
-# ATM drivers
-#
-CONFIG_ATM_TCP=m
-CONFIG_ATM_LANAI=m
-CONFIG_ATM_ENI=m
-# CONFIG_ATM_ENI_DEBUG is not set
-# CONFIG_ATM_ENI_TUNE_BURST is not set
-CONFIG_ATM_FIRESTREAM=m
-CONFIG_ATM_ZATM=m
-# CONFIG_ATM_ZATM_DEBUG is not set
-CONFIG_ATM_ZATM_EXACT_TS=y
-CONFIG_ATM_NICSTAR=m
-CONFIG_ATM_NICSTAR_USE_SUNI=y
-CONFIG_ATM_NICSTAR_USE_IDT77105=y
-CONFIG_ATM_IDT77252=m
-# CONFIG_ATM_IDT77252_DEBUG is not set
-# CONFIG_ATM_IDT77252_RCV_ALL is not set
-CONFIG_ATM_IDT77252_USE_SUNI=y
-CONFIG_ATM_AMBASSADOR=m
-# CONFIG_ATM_AMBASSADOR_DEBUG is not set
-CONFIG_ATM_HORIZON=m
-# CONFIG_ATM_HORIZON_DEBUG is not set
-CONFIG_ATM_IA=m
-# CONFIG_ATM_IA_DEBUG is not set
-CONFIG_ATM_FORE200E_MAYBE=m
-CONFIG_ATM_FORE200E_PCA=y
-CONFIG_ATM_FORE200E_PCA_DEFAULT_FW=y
-CONFIG_ATM_FORE200E_TX_RETRY=16
-CONFIG_ATM_FORE200E_DEBUG=0
-CONFIG_ATM_FORE200E=m
-
-#
-# Amateur Radio support
-#
-CONFIG_HAMRADIO=y
-CONFIG_AX25=m
-# CONFIG_AX25_DAMA_SLAVE is not set
-CONFIG_NETROM=m
-CONFIG_ROSE=m
-
-#
-# AX.25 network device drivers
-#
-# CONFIG_MKISS is not set
-# CONFIG_6PACK is not set
-# CONFIG_BPQETHER is not set
-# CONFIG_DMASCC is not set
-# CONFIG_SCC is not set
-# CONFIG_BAYCOM_SER_FDX is not set
-# CONFIG_BAYCOM_SER_HDX is not set
-# CONFIG_BAYCOM_PAR is not set
-# CONFIG_BAYCOM_EPP is not set
-CONFIG_SOUNDMODEM=m
-CONFIG_SOUNDMODEM_SBC=y
-CONFIG_SOUNDMODEM_WSS=y
-CONFIG_SOUNDMODEM_AFSK1200=y
-CONFIG_SOUNDMODEM_AFSK2400_7=y
-CONFIG_SOUNDMODEM_AFSK2400_8=y
-CONFIG_SOUNDMODEM_AFSK2666=y
-CONFIG_SOUNDMODEM_HAPN4800=y
-CONFIG_SOUNDMODEM_PSK4800=y
-CONFIG_SOUNDMODEM_FSK9600=y
-# CONFIG_YAM is not set
-
-#
-# IrDA (infrared) support
-#
-CONFIG_IRDA=m
-CONFIG_IRLAN=m
-CONFIG_IRNET=m
-CONFIG_IRCOMM=m
-CONFIG_IRDA_ULTRA=y
-CONFIG_IRDA_CACHE_LAST_LSAP=y
-CONFIG_IRDA_FAST_RR=y
-# CONFIG_IRDA_DEBUG is not set
-
-#
-# Infrared-port device drivers
-#
-CONFIG_IRTTY_SIR=m
-CONFIG_IRPORT_SIR=m
-CONFIG_DONGLE=y
-CONFIG_ESI_DONGLE=m
-CONFIG_ACTISYS_DONGLE=m
-CONFIG_TEKRAM_DONGLE=m
-CONFIG_GIRBIL_DONGLE=m
-CONFIG_LITELINK_DONGLE=m
-CONFIG_MCP2120_DONGLE=m
-CONFIG_OLD_BELKIN_DONGLE=m
-CONFIG_ACT200L_DONGLE=m
-CONFIG_MA600_DONGLE=m
-CONFIG_USB_IRDA=m
-CONFIG_NSC_FIR=m
-CONFIG_WINBOND_FIR=m
-CONFIG_TOSHIBA_OLD=m
-CONFIG_TOSHIBA_FIR=m
-CONFIG_SMC_IRCC_FIR=m
-CONFIG_ALI_FIR=m
-CONFIG_VLSI_FIR=m
-
-#
-# ISDN subsystem
-#
-CONFIG_ISDN=m
-CONFIG_ISDN_BOOL=y
-CONFIG_ISDN_PPP=y
-CONFIG_ISDN_PPP_VJ=y
-CONFIG_ISDN_MPP=y
-CONFIG_ISDN_PPP_BSDCOMP=m
-CONFIG_ISDN_AUDIO=y
-CONFIG_ISDN_TTY_FAX=y
-
-#
-# ISDN feature submodules
-#
-CONFIG_ISDN_DRV_LOOP=m
-# CONFIG_ISDN_DIVERSION is not set
-
-#
-# Passive ISDN cards
-#
-CONFIG_ISDN_DRV_HISAX=m
-CONFIG_ISDN_HISAX=y
-CONFIG_HISAX_EURO=y
-CONFIG_DE_AOC=y
-# CONFIG_HISAX_NO_SENDCOMPLETE is not set
-# CONFIG_HISAX_NO_LLC is not set
-# CONFIG_HISAX_NO_KEYPAD is not set
-CONFIG_HISAX_1TR6=y
-CONFIG_HISAX_NI1=y
-CONFIG_HISAX_MAX_CARDS=8
-CONFIG_HISAX_16_0=y
-CONFIG_HISAX_16_3=y
-CONFIG_HISAX_AVM_A1=y
-CONFIG_HISAX_IX1MICROR2=y
-CONFIG_HISAX_ASUSCOM=y
-CONFIG_HISAX_TELEINT=y
-CONFIG_HISAX_HFCS=y
-CONFIG_HISAX_SPORTSTER=y
-CONFIG_HISAX_MIC=y
-CONFIG_HISAX_ISURF=y
-CONFIG_HISAX_HSTSAPHIR=y
-CONFIG_HISAX_TELESPCI=y
-CONFIG_HISAX_S0BOX=y
-CONFIG_HISAX_FRITZPCI=y
-CONFIG_HISAX_AVM_A1_PCMCIA=y
-CONFIG_HISAX_ELSA=y
-CONFIG_HISAX_DIEHLDIVA=y
-CONFIG_HISAX_SEDLBAUER=y
-CONFIG_HISAX_NETJET=y
-CONFIG_HISAX_NETJET_U=y
-CONFIG_HISAX_NICCY=y
-CONFIG_HISAX_BKM_A4T=y
-CONFIG_HISAX_SCT_QUADRO=y
-CONFIG_HISAX_GAZEL=y
-CONFIG_HISAX_HFC_PCI=y
-CONFIG_HISAX_W6692=y
-CONFIG_HISAX_HFC_SX=y
-CONFIG_HISAX_ENTERNOW_PCI=y
-CONFIG_HISAX_DEBUG=y
-CONFIG_HISAX_SEDLBAUER_CS=m
-CONFIG_HISAX_ELSA_CS=m
-CONFIG_HISAX_AVM_A1_CS=m
-CONFIG_HISAX_ST5481=m
-CONFIG_HISAX_FRITZ_PCIPNP=m
-
-#
-# Active ISDN cards
-#
-CONFIG_ISDN_DRV_ICN=m
-CONFIG_ISDN_DRV_PCBIT=m
-# CONFIG_ISDN_DRV_SC is not set
-# CONFIG_ISDN_DRV_ACT2000 is not set
-CONFIG_ISDN_DRV_EICON=y
-CONFIG_ISDN_DRV_EICON_DIVAS=m
-# CONFIG_ISDN_DRV_EICON_OLD is not set
-CONFIG_ISDN_DRV_TPAM=m
-CONFIG_ISDN_CAPI=m
-CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
-CONFIG_ISDN_CAPI_MIDDLEWARE=y
-CONFIG_ISDN_CAPI_CAPI20=m
-CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
-CONFIG_ISDN_CAPI_CAPIFS=m
-CONFIG_ISDN_CAPI_CAPIDRV=m
-CONFIG_ISDN_DRV_AVMB1_B1ISA=m
-CONFIG_ISDN_DRV_AVMB1_B1PCI=m
-CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
-CONFIG_ISDN_DRV_AVMB1_T1ISA=m
-CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
-CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
-CONFIG_ISDN_DRV_AVMB1_T1PCI=m
-CONFIG_ISDN_DRV_AVMB1_C4=m
-CONFIG_HYSDN=m
-CONFIG_HYSDN_CAPI=y
-CONFIG_KALLSYMS=y
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Input core support
-#
-CONFIG_INPUT=m
-CONFIG_INPUT_KEYBDEV=m
-CONFIG_INPUT_MOUSEDEV=m
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-CONFIG_INPUT_JOYDEV=m
-CONFIG_INPUT_EVDEV=m
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_ECC=m
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-CONFIG_SERIAL_EXTENDED=y
-CONFIG_SERIAL_MANY_PORTS=y
-CONFIG_SERIAL_SHARE_IRQ=y
-# CONFIG_SERIAL_DETECT_IRQ is not set
-CONFIG_SERIAL_MULTIPORT=y
-# CONFIG_HUB6 is not set
-CONFIG_SERIAL_NONSTANDARD=y
-CONFIG_COMPUTONE=m
-CONFIG_ROCKETPORT=m
-CONFIG_CYCLADES=m
-# CONFIG_CYZ_INTR is not set
-CONFIG_DIGIEPCA=m
-CONFIG_ESPSERIAL=m
-CONFIG_MOXA_INTELLIO=m
-CONFIG_MOXA_SMARTIO=m
-CONFIG_ISI=m
-CONFIG_SYNCLINK=m
-# CONFIG_SYNCLINKMP is not set
-CONFIG_N_HDLC=m
-CONFIG_RISCOM8=m
-CONFIG_SPECIALIX=m
-CONFIG_SPECIALIX_RTSCTS=y
-CONFIG_SX=m
-# CONFIG_RIO is not set
-CONFIG_STALDRV=y
-CONFIG_STALLION=m
-CONFIG_ISTALLION=m
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=2048
-CONFIG_PRINTER=m
-CONFIG_LP_CONSOLE=y
-CONFIG_PPDEV=m
-CONFIG_TIPAR=m
-
-#
-# I2C support
-#
-CONFIG_I2C=m
-CONFIG_I2C_ALGOBIT=m
-CONFIG_I2C_PHILIPSPAR=m
-CONFIG_I2C_ELV=m
-CONFIG_I2C_VELLEMAN=m
-# CONFIG_SCx200_I2C is not set
-# CONFIG_SCx200_ACB is not set
-CONFIG_I2C_ALGOPCF=m
-CONFIG_I2C_ELEKTOR=m
-CONFIG_I2C_MAINBOARD=y
-CONFIG_I2C_ALI1535=m
-CONFIG_I2C_ALI15X3=m
-CONFIG_I2C_HYDRA=m
-CONFIG_I2C_AMD756=m
-# CONFIG_I2C_TSUNAMI is not set
-CONFIG_I2C_I801=m
-CONFIG_I2C_I810=m
-CONFIG_I2C_PIIX4=m
-CONFIG_I2C_SIS5595=m
-CONFIG_I2C_VIA=m
-CONFIG_I2C_VIAPRO=m
-CONFIG_I2C_VOODOO3=m
-CONFIG_I2C_ISA=m
-CONFIG_I2C_CHARDEV=m
-CONFIG_I2C_PROC=m
-
-#
-# Hardware sensors support
-#
-CONFIG_SENSORS=y
-CONFIG_SENSORS_ADM1021=m
-CONFIG_SENSORS_ADM1024=m
-CONFIG_SENSORS_ADM1025=m
-CONFIG_SENSORS_ADM9240=m
-CONFIG_SENSORS_DS1621=m
-CONFIG_SENSORS_FSCPOS=m
-CONFIG_SENSORS_FSCSCY=m
-CONFIG_SENSORS_GL518SM=m
-CONFIG_SENSORS_GL520SM=m
-CONFIG_SENSORS_MAXILIFE=m
-CONFIG_SENSORS_IT87=m
-CONFIG_SENSORS_MTP008=m
-CONFIG_SENSORS_LM75=m
-CONFIG_SENSORS_LM78=m
-CONFIG_SENSORS_LM80=m
-CONFIG_SENSORS_LM87=m
-CONFIG_SENSORS_LM92=m
-CONFIG_SENSORS_SIS5595=m
-CONFIG_SENSORS_SMSC47M1=m
-CONFIG_SENSORS_THMC50=m
-CONFIG_SENSORS_VIA686A=m
-CONFIG_SENSORS_VT1211=m
-CONFIG_SENSORS_VT8231=m
-CONFIG_SENSORS_W83781D=m
-CONFIG_SENSORS_OTHER=y
-CONFIG_SENSORS_BT869=m
-CONFIG_SENSORS_DDCMON=m
-CONFIG_SENSORS_EEPROM=m
-CONFIG_SENSORS_MATORB=m
-CONFIG_SENSORS_PCF8574=m
-CONFIG_SENSORS_PCF8591=m
-
-#
-# Mice
-#
-CONFIG_BUSMOUSE=m
-CONFIG_ATIXL_BUSMOUSE=m
-CONFIG_LOGIBUSMOUSE=m
-CONFIG_MS_BUSMOUSE=m
-CONFIG_MOUSE=y
-CONFIG_PSMOUSE=y
-CONFIG_82C710_MOUSE=m
-CONFIG_PC110_PAD=m
-CONFIG_MK712_MOUSE=m
-
-#
-# Joysticks
-#
-CONFIG_INPUT_GAMEPORT=m
-CONFIG_INPUT_NS558=m
-CONFIG_INPUT_LIGHTNING=m
-CONFIG_INPUT_PCIGAME=m
-CONFIG_INPUT_CS461X=m
-CONFIG_INPUT_EMU10K1=m
-CONFIG_INPUT_SERIO=m
-CONFIG_INPUT_SERPORT=m
-CONFIG_INPUT_ANALOG=m
-CONFIG_INPUT_A3D=m
-CONFIG_INPUT_ADI=m
-CONFIG_INPUT_COBRA=m
-CONFIG_INPUT_GF2K=m
-CONFIG_INPUT_GRIP=m
-CONFIG_INPUT_INTERACT=m
-CONFIG_INPUT_TMDC=m
-CONFIG_INPUT_SIDEWINDER=m
-CONFIG_INPUT_IFORCE_USB=m
-CONFIG_INPUT_IFORCE_232=m
-CONFIG_INPUT_WARRIOR=m
-CONFIG_INPUT_MAGELLAN=m
-CONFIG_INPUT_SPACEORB=m
-CONFIG_INPUT_SPACEBALL=m
-CONFIG_INPUT_STINGER=m
-CONFIG_INPUT_DB9=m
-CONFIG_INPUT_GAMECON=m
-CONFIG_INPUT_TURBOGRAFX=m
-# CONFIG_QIC02_TAPE is not set
-CONFIG_IPMI_HANDLER=m
-# CONFIG_IPMI_PANIC_EVENT is not set
-CONFIG_IPMI_DEVICE_INTERFACE=m
-CONFIG_IPMI_KCS=m
-CONFIG_IPMI_WATCHDOG=m
-
-#
-# Watchdog Cards
-#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-CONFIG_ACQUIRE_WDT=m
-CONFIG_ADVANTECH_WDT=m
-CONFIG_ALIM7101_WDT=m
-CONFIG_SC520_WDT=m
-CONFIG_PCWATCHDOG=m
-CONFIG_EUROTECH_WDT=m
-CONFIG_IB700_WDT=m
-CONFIG_WAFER_WDT=m
-CONFIG_I810_TCO=m
-# CONFIG_MIXCOMWD is not set
-# CONFIG_60XX_WDT is not set
-CONFIG_SC1200_WDT=m
-# CONFIG_SCx200_WDT is not set
-CONFIG_SOFT_WATCHDOG=m
-CONFIG_W83877F_WDT=m
-CONFIG_WDT=m
-CONFIG_WDTPCI=m
-# CONFIG_WDT_501 is not set
-CONFIG_MACHZ_WDT=m
-CONFIG_AMD7XX_TCO=m
-# CONFIG_SCx200_GPIO is not set
-CONFIG_AMD_RNG=m
-CONFIG_INTEL_RNG=m
-CONFIG_AMD_PM768=m
-CONFIG_NVRAM=m
-CONFIG_RTC=y
-CONFIG_DTLK=m
-CONFIG_R3964=m
-# CONFIG_APPLICOM is not set
-CONFIG_SONYPI=m
-
-#
-# Ftape, the floppy tape device driver
-#
-CONFIG_FTAPE=m
-CONFIG_ZFTAPE=m
-CONFIG_ZFT_DFLT_BLK_SZ=10240
-CONFIG_ZFT_COMPRESSOR=m
-CONFIG_FT_NR_BUFFERS=3
-# CONFIG_FT_PROC_FS is not set
-CONFIG_FT_NORMAL_DEBUG=y
-# CONFIG_FT_FULL_DEBUG is not set
-# CONFIG_FT_NO_TRACE is not set
-# CONFIG_FT_NO_TRACE_AT_ALL is not set
-CONFIG_FT_STD_FDC=y
-# CONFIG_FT_MACH2 is not set
-# CONFIG_FT_PROBE_FC10 is not set
-# CONFIG_FT_ALT_FDC is not set
-CONFIG_FT_FDC_THR=8
-CONFIG_FT_FDC_MAX_RATE=2000
-CONFIG_FT_ALPHA_CLOCK=0
-CONFIG_AGP=m
-CONFIG_AGP_INTEL=y
-CONFIG_AGP_I810=y
-CONFIG_AGP_VIA=y
-CONFIG_AGP_AMD=y
-CONFIG_AGP_AMD_8151=y
-CONFIG_AGP_SIS=y
-CONFIG_AGP_ALI=y
-CONFIG_AGP_SWORKS=y
-CONFIG_DRM=y
-# CONFIG_DRM_OLD is not set
-CONFIG_DRM_NEW=y
-CONFIG_DRM_TDFX=m
-CONFIG_DRM_R128=m
-CONFIG_DRM_RADEON=m
-CONFIG_DRM_I810=m
-# CONFIG_DRM_I810_XFREE_41 is not set
-CONFIG_DRM_I830=m
-CONFIG_DRM_MGA=m
-CONFIG_DRM_SIS=m
-
-#
-# PCMCIA character devices
-#
-CONFIG_PCMCIA_SERIAL_CS=m
-CONFIG_SYNCLINK_CS=m
-CONFIG_MWAVE=m
-CONFIG_BATTERY_GERICOM=m
-
-#
-# Multimedia devices
-#
-CONFIG_VIDEO_DEV=m
-
-#
-# Video For Linux
-#
-CONFIG_VIDEO_PROC_FS=y
-CONFIG_I2C_PARPORT=m
-CONFIG_VIDEO_BT848=m
-CONFIG_VIDEO_PMS=m
-CONFIG_VIDEO_BWQCAM=m
-CONFIG_VIDEO_CQCAM=m
-CONFIG_VIDEO_W9966=m
-CONFIG_VIDEO_CPIA=m
-CONFIG_VIDEO_CPIA_PP=m
-CONFIG_VIDEO_CPIA_USB=m
-CONFIG_VIDEO_SAA5249=m
-CONFIG_TUNER_3036=m
-CONFIG_VIDEO_STRADIS=m
-CONFIG_VIDEO_ZORAN=m
-CONFIG_VIDEO_ZORAN_BUZ=m
-CONFIG_VIDEO_ZORAN_DC10=m
-CONFIG_VIDEO_ZORAN_LML33=m
-CONFIG_VIDEO_ZR36120=m
-CONFIG_VIDEO_MEYE=m
-
-#
-# Radio Adapters
-#
-CONFIG_RADIO_CADET=m
-CONFIG_RADIO_RTRACK=m
-CONFIG_RADIO_RTRACK2=m
-CONFIG_RADIO_AZTECH=m
-CONFIG_RADIO_GEMTEK=m
-CONFIG_RADIO_GEMTEK_PCI=m
-CONFIG_RADIO_MAXIRADIO=m
-CONFIG_RADIO_MAESTRO=m
-CONFIG_RADIO_MIROPCM20=m
-CONFIG_RADIO_MIROPCM20_RDS=m
-CONFIG_RADIO_SF16FMI=m
-CONFIG_RADIO_SF16FMR2=m
-CONFIG_RADIO_TERRATEC=m
-CONFIG_RADIO_TRUST=m
-CONFIG_RADIO_TYPHOON=m
-CONFIG_RADIO_TYPHOON_PROC_FS=y
-CONFIG_RADIO_ZOLTRIX=m
-
-#
-# Crypto Hardware support
-#
-CONFIG_CRYPTO=m
-CONFIG_CRYPTO_BROADCOM=m
-
-#
-# File systems
-#
-CONFIG_QUOTA=y
-# CONFIG_QFMT_V1 is not set
-CONFIG_QFMT_V2=y
-# CONFIG_QIFACE_COMPAT is not set
-CONFIG_AUTOFS_FS=m
-CONFIG_AUTOFS4_FS=m
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-CONFIG_REISERFS_PROC_INFO=y
-# CONFIG_ADFS_FS is not set
-CONFIG_AFS_FS=m
-# CONFIG_ADFS_FS_RW is not set
-# CONFIG_AFFS_FS is not set
-CONFIG_HFS_FS=m
-CONFIG_BEFS_FS=m
-# CONFIG_BEFS_DEBUG is not set
-CONFIG_BFS_FS=m
-CONFIG_EXT3_FS=m
-CONFIG_EXT3_FS_XATTR=y
-CONFIG_EXT3_FS_XATTR_SHARING=y
-CONFIG_EXT3_FS_XATTR_USER=y
-CONFIG_JBD=m
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_UMSDOS_FS=m
-CONFIG_VFAT_FS=m
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-CONFIG_CRAMFS=m
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_JFS_FS=m
-CONFIG_JFS_DEBUG=y
-# CONFIG_JFS_STATISTICS is not set
-CONFIG_MINIX_FS=m
-CONFIG_VXFS_FS=m
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_RW is not set
-# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-CONFIG_ROMFS_FS=m
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XATTR_SHARING is not set
-# CONFIG_EXT2_FS_XATTR_USER is not set
-CONFIG_SYSV_FS=m
-CONFIG_UDF_FS=m
-CONFIG_UDF_RW=y
-CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
-
-#
-# Network File Systems
-#
-CONFIG_CODA_FS=m
-CONFIG_INTERMEZZO_FS=m
-CONFIG_NFS_FS=m
-CONFIG_NFS_V3=y
-# CONFIG_ROOT_NFS is not set
-CONFIG_NFSD=m
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_TCP is not set
-CONFIG_SUNRPC=m
-CONFIG_LOCKD=m
-CONFIG_LOCKD_V4=y
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
-CONFIG_NCP_FS=m
-CONFIG_NCPFS_PACKET_SIGNING=y
-CONFIG_NCPFS_IOCTL_LOCKING=y
-CONFIG_NCPFS_STRONG=y
-CONFIG_NCPFS_NFS_NS=y
-CONFIG_NCPFS_OS2_NS=y
-CONFIG_NCPFS_SMALLDOS=y
-CONFIG_NCPFS_NLS=y
-CONFIG_NCPFS_EXTRAS=y
-CONFIG_ZISOFS_FS=y
-CONFIG_FS_MBCACHE=y
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-CONFIG_OSF_PARTITION=y
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
-CONFIG_BSD_DISKLABEL=y
-CONFIG_MINIX_SUBPARTITION=y
-CONFIG_SOLARIS_X86_PARTITION=y
-CONFIG_UNIXWARE_DISKLABEL=y
-# CONFIG_LDM_PARTITION is not set
-CONFIG_SGI_PARTITION=y
-# CONFIG_ULTRIX_PARTITION is not set
-CONFIG_SUN_PARTITION=y
-# CONFIG_EFI_PARTITION is not set
-CONFIG_SMB_NLS=y
-CONFIG_NLS=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=m
-
-#
-# Console drivers
-#
-CONFIG_VGA_CONSOLE=y
-CONFIG_VIDEO_SELECT=y
-# CONFIG_VIDEO_IGNORE_BAD_MODE is not set
-CONFIG_MDA_CONSOLE=m
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FB_RIVA=m
-CONFIG_FB_CLGEN=m
-CONFIG_FB_PM2=m
-# CONFIG_FB_PM2_FIFO_DISCONNECT is not set
-CONFIG_FB_PM2_PCI=y
-CONFIG_FB_PM3=m
-# CONFIG_FB_CYBER2000 is not set
-CONFIG_FB_VESA=y
-CONFIG_FB_VGA16=m
-CONFIG_FB_HGA=m
-CONFIG_VIDEO_SELECT=y
-CONFIG_FB_MATROX=m
-CONFIG_FB_MATROX_MILLENIUM=y
-CONFIG_FB_MATROX_MYSTIQUE=y
-# CONFIG_FB_MATROX_G450 is not set
-CONFIG_FB_MATROX_G100A=y
-CONFIG_FB_MATROX_G100=y
-CONFIG_FB_MATROX_I2C=m
-CONFIG_FB_MATROX_MAVEN=m
-# CONFIG_FB_MATROX_PROC is not set
-CONFIG_FB_MATROX_MULTIHEAD=y
-CONFIG_FB_ATY=m
-CONFIG_FB_ATY_GX=y
-CONFIG_FB_ATY_CT=y
-CONFIG_FB_ATY_CT_VAIO_LCD=y
-CONFIG_FB_RADEON=m
-CONFIG_FB_ATY128=m
-CONFIG_FB_SIS=m
-CONFIG_FB_SIS_300=y
-CONFIG_FB_SIS_315=y
-CONFIG_FB_NEOMAGIC=m
-CONFIG_FB_3DFX=m
-CONFIG_FB_VOODOO1=m
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-# CONFIG_FBCON_ADVANCED is not set
-CONFIG_FBCON_MFB=m
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-CONFIG_FBCON_CFB24=y
-CONFIG_FBCON_CFB32=y
-CONFIG_FBCON_VGA_PLANES=m
-CONFIG_FBCON_HGA=m
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-# CONFIG_FBCON_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Sound
-#
-CONFIG_SOUND=m
-CONFIG_SOUND_ALI5455=m
-CONFIG_SOUND_BT878=m
-CONFIG_SOUND_CMPCI=m
-CONFIG_SOUND_CMPCI_FM=y
-CONFIG_SOUND_CMPCI_FMIO=388
-CONFIG_SOUND_CMPCI_FMIO=388
-CONFIG_SOUND_CMPCI_MIDI=y
-CONFIG_SOUND_CMPCI_MPUIO=330
-CONFIG_SOUND_CMPCI_JOYSTICK=y
-CONFIG_SOUND_CMPCI_CM8738=y
-# CONFIG_SOUND_CMPCI_SPDIFINVERSE is not set
-CONFIG_SOUND_CMPCI_SPDIFLOOP=y
-CONFIG_SOUND_CMPCI_SPEAKERS=2
-CONFIG_SOUND_EMU10K1=m
-CONFIG_MIDI_EMU10K1=y
-CONFIG_SOUND_AUDIGY=m
-CONFIG_SOUND_FUSION=m
-CONFIG_SOUND_CS4281=m
-CONFIG_SOUND_ES1370=m
-CONFIG_SOUND_ES1371=m
-CONFIG_SOUND_ESSSOLO1=m
-CONFIG_SOUND_MAESTRO=m
-CONFIG_SOUND_MAESTRO3=m
-CONFIG_SOUND_FORTE=m
-CONFIG_SOUND_ICH=m
-CONFIG_SOUND_RME96XX=m
-CONFIG_SOUND_SONICVIBES=m
-CONFIG_SOUND_TRIDENT=m
-CONFIG_SOUND_MSNDCLAS=m
-# CONFIG_MSNDCLAS_HAVE_BOOT is not set
-CONFIG_MSNDCLAS_INIT_FILE="/etc/sound/msndinit.bin"
-CONFIG_MSNDCLAS_PERM_FILE="/etc/sound/msndperm.bin"
-CONFIG_SOUND_MSNDPIN=m
-# CONFIG_MSNDPIN_HAVE_BOOT is not set
-CONFIG_MSNDPIN_INIT_FILE="/etc/sound/pndspini.bin"
-CONFIG_MSNDPIN_PERM_FILE="/etc/sound/pndsperm.bin"
-CONFIG_SOUND_VIA82CXXX=m
-CONFIG_MIDI_VIA82CXXX=y
-CONFIG_SOUND_OSS=m
-# CONFIG_SOUND_TRACEINIT is not set
-CONFIG_SOUND_DMAP=y
-CONFIG_SOUND_AD1816=m
-CONFIG_SOUND_AD1889=m
-CONFIG_SOUND_SGALAXY=m
-CONFIG_SOUND_ADLIB=m
-CONFIG_SOUND_ACI_MIXER=m
-CONFIG_SOUND_CS4232=m
-CONFIG_SOUND_SSCAPE=m
-CONFIG_SOUND_GUS=m
-CONFIG_SOUND_GUS16=y
-CONFIG_SOUND_GUSMAX=y
-CONFIG_SOUND_VMIDI=m
-CONFIG_SOUND_TRIX=m
-CONFIG_SOUND_MSS=m
-CONFIG_SOUND_MPU401=m
-CONFIG_SOUND_NM256=m
-CONFIG_SOUND_MAD16=m
-CONFIG_MAD16_OLDCARD=y
-CONFIG_SOUND_PAS=m
-# CONFIG_PAS_JOYSTICK is not set
-CONFIG_SOUND_PSS=m
-# CONFIG_PSS_MIXER is not set
-# CONFIG_PSS_HAVE_BOOT is not set
-CONFIG_SOUND_SB=m
-CONFIG_SOUND_AWE32_SYNTH=m
-CONFIG_SOUND_WAVEFRONT=m
-CONFIG_SOUND_MAUI=m
-CONFIG_SOUND_YM3812=m
-CONFIG_SOUND_OPL3SA1=m
-CONFIG_SOUND_OPL3SA2=m
-CONFIG_SOUND_YMFPCI=m
-CONFIG_SOUND_YMFPCI_LEGACY=y
-CONFIG_SOUND_UART6850=m
-CONFIG_SOUND_AEDSP16=m
-CONFIG_SC6600=y
-CONFIG_SC6600_JOY=y
-CONFIG_SC6600_CDROM=4
-CONFIG_SC6600_CDROMBASE=0
-CONFIG_AEDSP16_SBPRO=y
-CONFIG_AEDSP16_MPU401=y
-CONFIG_SOUND_TVMIXER=m
-
-#
-# USB support
-#
-CONFIG_USB=m
-# CONFIG_USB_DEBUG is not set
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
-CONFIG_USB_EHCI_HCD=m
-CONFIG_USB_UHCI=m
-CONFIG_USB_UHCI_ALT=m
-CONFIG_USB_OHCI=m
-CONFIG_USB_AUDIO=m
-# CONFIG_USB_EMI26 is not set
-CONFIG_USB_MIDI=m
-CONFIG_USB_STORAGE=m
-# CONFIG_USB_STORAGE_DEBUG is not set
-CONFIG_USB_STORAGE_DATAFAB=y
-CONFIG_USB_STORAGE_FREECOM=y
-CONFIG_USB_STORAGE_ISD200=y
-CONFIG_USB_STORAGE_DPCM=y
-CONFIG_USB_STORAGE_HP8200e=y
-CONFIG_USB_STORAGE_SDDR09=y
-CONFIG_USB_STORAGE_SDDR55=y
-CONFIG_USB_STORAGE_JUMPSHOT=y
-CONFIG_USB_ACM=m
-CONFIG_USB_PRINTER=m
-CONFIG_USB_HID=m
-CONFIG_USB_HIDINPUT=y
-CONFIG_USB_HIDDEV=y
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
-CONFIG_USB_AIPTEK=m
-CONFIG_USB_WACOM=m
-CONFIG_USB_POWERMATE=m
-# CONFIG_USB_DC2XX is not set
-CONFIG_USB_MDC800=m
-CONFIG_USB_SCANNER=m
-CONFIG_USB_MICROTEK=m
-CONFIG_USB_HPUSBSCSI=m
-CONFIG_USB_IBMCAM=m
-CONFIG_USB_OV511=m
-CONFIG_USB_PWC=m
-CONFIG_USB_SE401=m
-CONFIG_USB_STV680=m
-CONFIG_USB_VICAM=m
-CONFIG_USB_DSBR=m
-CONFIG_USB_DABUSB=m
-CONFIG_USB_PEGASUS=m
-CONFIG_USB_RTL8150=m
-CONFIG_USB_KAWETH=m
-CONFIG_USB_CATC=m
-CONFIG_USB_CDCETHER=m
-CONFIG_USB_USBNET=m
-CONFIG_USB_USS720=m
-
-#
-# USB Serial Converter support
-#
-CONFIG_USB_SERIAL=m
-# CONFIG_USB_SERIAL_DEBUG is not set
-CONFIG_USB_SERIAL_GENERIC=y
-CONFIG_USB_SERIAL_BELKIN=m
-CONFIG_USB_SERIAL_WHITEHEAT=m
-CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
-CONFIG_USB_SERIAL_EMPEG=m
-CONFIG_USB_SERIAL_FTDI_SIO=m
-CONFIG_USB_SERIAL_VISOR=m
-CONFIG_USB_SERIAL_IPAQ=m
-CONFIG_USB_SERIAL_IR=m
-CONFIG_USB_SERIAL_EDGEPORT=m
-CONFIG_USB_SERIAL_EDGEPORT_TI=m
-CONFIG_USB_SERIAL_KEYSPAN_PDA=m
-CONFIG_USB_SERIAL_KEYSPAN=m
-# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
-CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
-# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
-CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
-# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
-CONFIG_USB_SERIAL_MCT_U232=m
-CONFIG_USB_SERIAL_KLSI=m
-CONFIG_USB_SERIAL_KOBIL_SCT=m
-CONFIG_USB_SERIAL_PL2303=m
-CONFIG_USB_SERIAL_CYBERJACK=m
-CONFIG_USB_SERIAL_XIRCOM=m
-CONFIG_USB_SERIAL_OMNINET=m
-CONFIG_USB_RIO500=m
-CONFIG_USB_AUERSWALD=m
-CONFIG_USB_TIGL=m
-CONFIG_USB_BRLVGER=m
-CONFIG_USB_LCD=m
-
-#
-# Additional device driver support
-#
-CONFIG_NET_BROADCOM=m
-CONFIG_CIPE=m
-CONFIG_CRYPTO_AEP=m
-CONFIG_MEGARAC=m
-CONFIG_FC_QLA2200=m
-CONFIG_FC_QLA2300=m
-CONFIG_SCSI_ISCSI=m
-
-#
-# Bluetooth support
-#
-CONFIG_BLUEZ=m
-CONFIG_BLUEZ_L2CAP=m
-CONFIG_BLUEZ_SCO=m
-CONFIG_BLUEZ_RFCOMM=m
-CONFIG_BLUEZ_RFCOMM_TTY=y
-CONFIG_BLUEZ_BNEP=m
-CONFIG_BLUEZ_BNEP_MC_FILTER=y
-CONFIG_BLUEZ_BNEP_PROTO_FILTER=y
-
-#
-# Bluetooth device drivers
-#
-CONFIG_BLUEZ_HCIUSB=m
-CONFIG_BLUEZ_USB_ZERO_PACKET=y
-CONFIG_BLUEZ_HCIUART=m
-CONFIG_BLUEZ_HCIUART_H4=y
-CONFIG_BLUEZ_HCIUART_BCSP=y
-CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y
-CONFIG_BLUEZ_HCIDTL1=m
-CONFIG_BLUEZ_HCIBT3C=m
-CONFIG_BLUEZ_HCIBLUECARD=m
-CONFIG_BLUEZ_HCIBTUART=m
-CONFIG_BLUEZ_HCIVHCI=m
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_STACKOVERFLOW=y
-# CONFIG_DEBUG_HIGHMEM is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_IOVIRT is not set
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_FRAME_POINTER is not set
-CONFIG_MCL_COREDUMP=y
-CONFIG_BOOTIMG=y
-
-#
-# Library routines
-#
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
+++ /dev/null
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_USERMODE=y
-# CONFIG_ISA is not set
-# CONFIG_SBUS is not set
-# CONFIG_PCI is not set
-CONFIG_UID16=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General Setup
-#
-# CONFIG_MODE_SKAS is not set
-CONFIG_MODE_TT=y
-CONFIG_MODE_TT=y
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-# CONFIG_BINFMT_AOUT is not set
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=y
-CONFIG_HOSTFS=y
-# CONFIG_HPPFS is not set
-CONFIG_MCONSOLE=y
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_HOST_2G_2G is not set
-# CONFIG_UML_SMP is not set
-# CONFIG_SMP is not set
-CONFIG_NEST_LEVEL=0
-CONFIG_KERNEL_HALF_GIGS=1
-# CONFIG_HIGHMEM is not set
-# CONFIG_PROC_MM is not set
-CONFIG_KERNEL_STACK_ORDER=3
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_KMOD=y
-
-#
-# Character Devices
-#
-CONFIG_STDIO_CONSOLE=y
-CONFIG_SSL=y
-CONFIG_FD_CHAN=y
-# CONFIG_NULL_CHAN is not set
-CONFIG_PORT_CHAN=y
-CONFIG_PTY_CHAN=y
-CONFIG_TTY_CHAN=y
-CONFIG_XTERM_CHAN=y
-CONFIG_CON_ZERO_CHAN="fd:0,fd:1"
-CONFIG_CON_CHAN="xterm"
-CONFIG_SSL_CHAN="pty"
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-# CONFIG_WATCHDOG is not set
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-# CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_UML_WATCHDOG is not set
-# CONFIG_UML_SOUND is not set
-# CONFIG_SOUND is not set
-# CONFIG_HOSTAUDIO is not set
-# CONFIG_TTY_LOG is not set
-
-#
-# Block Devices
-#
-CONFIG_BLK_DEV_UBD=y
-# CONFIG_BLK_DEV_UBD_SYNC is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_MMAPPER is not set
-CONFIG_NETDEVICES=y
-
-#
-# Network Devices
-#
-CONFIG_UML_NET=y
-CONFIG_UML_NET_ETHERTAP=y
-CONFIG_UML_NET_TUNTAP=y
-CONFIG_UML_NET_SLIP=y
-# CONFIG_UML_NET_SLIRP is not set
-CONFIG_UML_NET_DAEMON=y
-CONFIG_UML_NET_MCAST=y
-# CONFIG_UML_NET_PCAP is not set
-CONFIG_DUMMY=y
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=y
-CONFIG_PPP=y
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-# CONFIG_PPP_ASYNC is not set
-# CONFIG_PPP_SYNC_TTY is not set
-# CONFIG_PPP_DEFLATE is not set
-# CONFIG_PPP_BSDCOMP is not set
-# CONFIG_PPPOE is not set
-CONFIG_SLIP=y
-# CONFIG_SLIP_COMPRESSED is not set
-# CONFIG_SLIP_SMART is not set
-# CONFIG_SLIP_MODE_SLIP6 is not set
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_IPV6 is not set
-# CONFIG_KHTTPD is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-
-#
-#
-#
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-
-#
-# Appletalk devices
-#
-# CONFIG_DEV_APPLETALK is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-
-#
-# File systems
-#
-CONFIG_QUOTA=y
-# CONFIG_AUTOFS_FS is not set
-CONFIG_AUTOFS4_FS=m
-CONFIG_REISERFS_FS=y
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_ADFS_FS is not set
-# CONFIG_ADFS_FS_RW is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BEFS_DEBUG is not set
-# CONFIG_BFS_FS is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_XATTR_SHARING is not set
-# CONFIG_EXT3_FS_XATTR_USER is not set
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-# CONFIG_CRAMFS is not set
-CONFIG_TMPFS=y
-CONFIG_TMPFS_XATTR=y
-CONFIG_RAMFS=y
-# CONFIG_ISO9660_FS is not set
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_RW is not set
-# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XATTR_SHARING is not set
-# CONFIG_EXT2_FS_XATTR_USER is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
-# CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
-
-#
-# Network File Systems
-#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_NFS_FS is not set
-# CONFIG_NFS_V3 is not set
-# CONFIG_ROOT_NFS is not set
-# CONFIG_NFSD is not set
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-# CONFIG_SUNRPC is not set
-# CONFIG_LOCKD is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
-# CONFIG_ZISOFS_FS is not set
-CONFIG_FS_MBCACHE=y
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_SMB_NLS is not set
-# CONFIG_NLS is not set
-
-#
-# SCSI support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_BLK_DEV_LVM is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Library routines
-#
-# CONFIG_ZLIB_INFLATE is not set
-# CONFIG_ZLIB_DEFLATE is not set
-
-#
-# Kernel hacking
-#
-CONFIG_DEBUG_SLAB=y
-CONFIG_DEBUGSYM=y
-CONFIG_PT_PROXY=y
-# CONFIG_GPROF is not set
-# CONFIG_GCOV is not set
+++ /dev/null
-#
-# Automatically generated by make menuconfig: don't edit
-#
-CONFIG_USERMODE=y
-# CONFIG_ISA is not set
-# CONFIG_SBUS is not set
-# CONFIG_PCI is not set
-CONFIG_UID16=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General Setup
-#
-# CONFIG_MODE_SKAS is not set
-CONFIG_MODE_TT=y
-CONFIG_MODE_TT=y
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-# CONFIG_BINFMT_AOUT is not set
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=y
-CONFIG_HOSTFS=y
-# CONFIG_HPPFS is not set
-CONFIG_MCONSOLE=y
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_HOST_2G_2G is not set
-# CONFIG_UML_SMP is not set
-# CONFIG_SMP is not set
-CONFIG_NEST_LEVEL=0
-CONFIG_KERNEL_HALF_GIGS=1
-# CONFIG_HIGHMEM is not set
-# CONFIG_PROC_MM is not set
-CONFIG_KERNEL_STACK_ORDER=3
-CONFIG_UML_REAL_TIME_CLOCK=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_KMOD=y
-
-#
-# Character Devices
-#
-CONFIG_STDIO_CONSOLE=y
-CONFIG_SSL=y
-CONFIG_FD_CHAN=y
-# CONFIG_NULL_CHAN is not set
-CONFIG_PORT_CHAN=y
-CONFIG_PTY_CHAN=y
-CONFIG_TTY_CHAN=y
-CONFIG_XTERM_CHAN=y
-CONFIG_CON_ZERO_CHAN="fd:0,fd:1"
-CONFIG_CON_CHAN="xterm"
-CONFIG_SSL_CHAN="pty"
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-# CONFIG_WATCHDOG is not set
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-# CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_UML_WATCHDOG is not set
-# CONFIG_UML_SOUND is not set
-# CONFIG_SOUND is not set
-# CONFIG_HOSTAUDIO is not set
-# CONFIG_TTY_LOG is not set
-
-#
-# Block Devices
-#
-CONFIG_BLK_DEV_UBD=y
-# CONFIG_BLK_DEV_UBD_SYNC is not set
-# CONFIG_COW is not set
-CONFIG_COW_COMMON=y
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_MMAPPER is not set
-CONFIG_NETDEVICES=y
-
-#
-# Network Devices
-#
-CONFIG_UML_NET=y
-CONFIG_UML_NET_ETHERTAP=y
-CONFIG_UML_NET_TUNTAP=y
-CONFIG_UML_NET_SLIP=y
-# CONFIG_UML_NET_SLIRP is not set
-CONFIG_UML_NET_DAEMON=y
-CONFIG_UML_NET_MCAST=y
-# CONFIG_UML_NET_PCAP is not set
-CONFIG_DUMMY=y
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=y
-CONFIG_PPP=y
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-# CONFIG_PPP_ASYNC is not set
-# CONFIG_PPP_SYNC_TTY is not set
-# CONFIG_PPP_DEFLATE is not set
-# CONFIG_PPP_BSDCOMP is not set
-# CONFIG_PPPOE is not set
-CONFIG_SLIP=y
-# CONFIG_SLIP_COMPRESSED is not set
-# CONFIG_SLIP_SMART is not set
-# CONFIG_SLIP_MODE_SLIP6 is not set
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_IPV6 is not set
-# CONFIG_KHTTPD is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-
-#
-# Appletalk devices
-#
-# CONFIG_DEV_APPLETALK is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-
-#
-# File systems
-#
-CONFIG_QUOTA=y
-# CONFIG_QFMT_V2 is not set
-# CONFIG_AUTOFS_FS is not set
-CONFIG_AUTOFS4_FS=m
-CONFIG_REISERFS_FS=y
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_ADFS_FS is not set
-# CONFIG_ADFS_FS_RW is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BEFS_DEBUG is not set
-# CONFIG_BFS_FS is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_XATTR_SHARING is not set
-# CONFIG_EXT3_FS_XATTR_USER is not set
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-# CONFIG_CRAMFS is not set
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-# CONFIG_ISO9660_FS is not set
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_RW is not set
-# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XATTR_SHARING is not set
-# CONFIG_EXT2_FS_XATTR_USER is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
-# CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
-
-#
-# Network File Systems
-#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_NFS_FS is not set
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_ROOT_NFS is not set
-# CONFIG_NFSD is not set
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-# CONFIG_SUNRPC is not set
-# CONFIG_LOCKD is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
-# CONFIG_ZISOFS_FS is not set
-CONFIG_FS_MBCACHE=y
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_SMB_NLS is not set
-# CONFIG_NLS is not set
-
-#
-# SCSI support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_BLK_DEV_LVM is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-# CONFIG_ZLIB_INFLATE is not set
-# CONFIG_ZLIB_DEFLATE is not set
-
-#
-# Kernel hacking
-#
-CONFIG_DEBUG_SLAB=y
-CONFIG_DEBUGSYM=y
-CONFIG_PT_PROXY=y
-# CONFIG_GPROF is not set
-# CONFIG_GCOV is not set
+++ /dev/null
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_X86=y
-CONFIG_ISA=y
-# CONFIG_SBUS is not set
-CONFIG_UID16=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Processor type and features
-#
-CONFIG_LOLAT=y
-# CONFIG_LOLAT_SYSCTL is not set
-# CONFIG_M386 is not set
-# CONFIG_M486 is not set
-# CONFIG_M586 is not set
-# CONFIG_M586TSC is not set
-# CONFIG_M586MMX is not set
-# CONFIG_M686 is not set
-# CONFIG_MPENTIUMIII is not set
-CONFIG_MPENTIUM4=y
-# CONFIG_MK6 is not set
-# CONFIG_MK7 is not set
-# CONFIG_MELAN is not set
-# CONFIG_MCRUSOE is not set
-# CONFIG_MWINCHIPC6 is not set
-# CONFIG_MWINCHIP2 is not set
-# CONFIG_MWINCHIP3D is not set
-# CONFIG_MCYRIXIII is not set
-CONFIG_X86_WP_WORKS_OK=y
-CONFIG_X86_INVLPG=y
-CONFIG_X86_CMPXCHG=y
-CONFIG_X86_XADD=y
-CONFIG_X86_BSWAP=y
-CONFIG_X86_POPAD_OK=y
-# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_X86_L1_CACHE_SHIFT=7
-CONFIG_X86_TSC=y
-CONFIG_X86_GOOD_APIC=y
-CONFIG_X86_PGE=y
-CONFIG_X86_USE_PPRO_CHECKSUM=y
-CONFIG_X86_MCE=y
-# CONFIG_CPU_FREQ is not set
-# CONFIG_USE_IRQ_STACKS is not set
-# CONFIG_TOSHIBA is not set
-# CONFIG_I8K is not set
-CONFIG_MICROCODE=m
-CONFIG_X86_MSR=m
-CONFIG_X86_CPUID=m
-# CONFIG_E820_PROC is not set
-# CONFIG_NOHIGHMEM is not set
-CONFIG_HIGHMEM4G=y
-# CONFIG_HIGHMEM64G is not set
-CONFIG_HIGHMEM=y
-CONFIG_HIGHIO=y
-# CONFIG_MATH_EMULATION is not set
-CONFIG_MTRR=y
-CONFIG_SMP=y
-# CONFIG_MULTIQUAD is not set
-CONFIG_HAVE_DEC_LOCK=y
-
-#
-# General setup
-#
-CONFIG_HZ=100
-CONFIG_NET=y
-CONFIG_X86_IO_APIC=y
-CONFIG_X86_LOCAL_APIC=y
-CONFIG_PCI=y
-# CONFIG_PCI_GOBIOS is not set
-# CONFIG_PCI_GODIRECT is not set
-CONFIG_PCI_GOANY=y
-CONFIG_PCI_BIOS=y
-CONFIG_PCI_DIRECT=y
-CONFIG_PCI_NAMES=y
-
-#
-# Performance-monitoring counters support
-#
-CONFIG_PERFCTR=m
-CONFIG_KPERFCTR=y
-# CONFIG_PERFCTR_DEBUG is not set
-# CONFIG_PERFCTR_INIT_TESTS is not set
-CONFIG_PERFCTR_VIRTUAL=y
-CONFIG_PERFCTR_GLOBAL=y
-# CONFIG_EISA is not set
-# CONFIG_MCA is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
-# CONFIG_HOTPLUG_PCI is not set
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=m
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=m
-# CONFIG_IKCONFIG is not set
-CONFIG_PM=y
-
-#
-# Additional device driver support
-#
-# CONFIG_CIPE is not set
-# CONFIG_CRYPTO_AEP is not set
-# CONFIG_MEGARAC is not set
-CONFIG_FC_QLA2200=m
-CONFIG_FC_QLA2300=m
-# CONFIG_SCSI_ISCSI is not set
-CONFIG_IBMASM=m
-CONFIG_IBMSER=m
-CONFIG_NEW_DIGI_EPCA=m
-CONFIG_NVIDIA=m
-# CONFIG_ACPI is not set
-CONFIG_APM=y
-CONFIG_APM_IGNORE_USER_SUSPEND=y
-# CONFIG_APM_DO_ENABLE is not set
-# CONFIG_APM_CPU_IDLE is not set
-# CONFIG_APM_DISPLAY_BLANK is not set
-CONFIG_APM_RTC_IS_GMT=y
-# CONFIG_APM_ALLOW_INTS is not set
-# CONFIG_APM_REAL_MODE_POWER_OFF is not set
-
-#
-# Binary emulation of other systems
-#
-# CONFIG_ABI is not set
-# CONFIG_ABI_SVR4 is not set
-
-#
-# Support for foreign binary formats
-#
-# CONFIG_BINFMT_COFF is not set
-# CONFIG_BINFMT_XOUT is not set
-# CONFIG_BINFMT_XOUT_X286 is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_PARTITIONS is not set
-# CONFIG_MTD_CONCAT is not set
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=m
-# CONFIG_MTD_BLOCK is not set
-# CONFIG_MTD_BLOCK_RO is not set
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-# CONFIG_MTD_CFI is not set
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_GEN_PROBE=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_NOSWAP=y
-# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-CONFIG_MTD_CFI_GEOMETRY=y
-CONFIG_MTD_CFI_B1=y
-# CONFIG_MTD_CFI_B2 is not set
-# CONFIG_MTD_CFI_B4 is not set
-# CONFIG_MTD_CFI_B8 is not set
-CONFIG_MTD_CFI_I1=y
-# CONFIG_MTD_CFI_I2 is not set
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_AMDSTD=y
-# CONFIG_MTD_RAM is not set
-CONFIG_MTD_ROM=y
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-# CONFIG_MTD_AMDSTD is not set
-# CONFIG_MTD_SHARP is not set
-# CONFIG_MTD_JEDEC is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_PHYSMAP is not set
-# CONFIG_MTD_PNC2000 is not set
-# CONFIG_MTD_SC520CDP is not set
-# CONFIG_MTD_NETSC520 is not set
-# CONFIG_MTD_SBC_GXX is not set
-# CONFIG_MTD_ELAN_104NC is not set
-# CONFIG_MTD_DILNETPC is not set
-# CONFIG_MTD_MIXMEM is not set
-# CONFIG_MTD_OCTAGON is not set
-# CONFIG_MTD_VMAX is not set
-# CONFIG_MTD_L440GX is not set
-# CONFIG_MTD_AMD766ROM is not set
-CONFIG_MTD_ICH2ROM=m
-# CONFIG_MTD_PCI is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC1000 is not set
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOCPROBE is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Parallel port support
-#
-CONFIG_PARPORT=m
-CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_CML1=m
-# CONFIG_PARPORT_SERIAL is not set
-# CONFIG_PARPORT_PC_FIFO is not set
-# CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_AMIGA is not set
-# CONFIG_PARPORT_MFC3 is not set
-# CONFIG_PARPORT_ATARI is not set
-# CONFIG_PARPORT_GSC is not set
-# CONFIG_PARPORT_SUNBPP is not set
-# CONFIG_PARPORT_OTHER is not set
-CONFIG_PARPORT_1284=y
-
-#
-# Plug and Play configuration
-#
-CONFIG_PNP=y
-CONFIG_ISAPNP=y
-# CONFIG_PNPBIOS is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_FD=y
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_CISS_SCSI_TAPE is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_NBD=m
-# CONFIG_BLK_DEV_ENBD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-
-#
-# Multi-device support (RAID and LVM)
-#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-CONFIG_BLK_DEV_LVM=m
-
-#
-# Cryptography support (CryptoAPI)
-#
-# CONFIG_CRYPTO is not set
-# CONFIG_CIPHERS is not set
-# CONFIG_CRYPTODEV is not set
-# CONFIG_CRYPTOLOOP is not set
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_FILTER=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_TUX is not set
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_FWMARK=y
-CONFIG_IP_ROUTE_NAT=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_TOS=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_ROUTE_LARGE_TABLES=y
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-CONFIG_SYN_COOKIES=y
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-# CONFIG_IP_NF_FTP is not set
-# CONFIG_IP_NF_IRC is not set
-# CONFIG_IP_NF_QUEUE is not set
-CONFIG_IP_NF_IPTABLES=m
-# CONFIG_IP_NF_MATCH_LIMIT is not set
-# CONFIG_IP_NF_MATCH_MAC is not set
-# CONFIG_IP_NF_MATCH_MARK is not set
-# CONFIG_IP_NF_MATCH_MULTIPORT is not set
-# CONFIG_IP_NF_MATCH_TOS is not set
-# CONFIG_IP_NF_MATCH_AH_ESP is not set
-# CONFIG_IP_NF_MATCH_LENGTH is not set
-# CONFIG_IP_NF_MATCH_TTL is not set
-# CONFIG_IP_NF_MATCH_TCPMSS is not set
-CONFIG_IP_NF_MATCH_STATE=m
-# CONFIG_IP_NF_MATCH_UNCLEAN is not set
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_FILTER=m
-# CONFIG_IP_NF_TARGET_REJECT is not set
-# CONFIG_IP_NF_TARGET_MIRROR is not set
-# CONFIG_IP_NF_NAT is not set
-# CONFIG_IP_NF_MANGLE is not set
-CONFIG_IP_NF_TARGET_LOG=m
-# CONFIG_IP_NF_TARGET_ULOG is not set
-# CONFIG_IP_NF_TARGET_TCPMSS is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_KHTTPD=m
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-
-#
-#
-#
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-
-#
-# Appletalk devices
-#
-# CONFIG_DEV_APPLETALK is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-CONFIG_NET_PKTGEN=m
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-# CONFIG_PHONE_IXJ is not set
-# CONFIG_PHONE_IXJ_PCMCIA is not set
-
-#
-# ATA/IDE/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_IDEDISK_MULTI_MODE=y
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
-# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
-# CONFIG_BLK_DEV_IDEDISK_IBM is not set
-# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
-# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
-# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
-# CONFIG_BLK_DEV_IDEDISK_WD is not set
-# CONFIG_BLK_DEV_COMMERIAL is not set
-# CONFIG_BLK_DEV_TIVO is not set
-# CONFIG_BLK_DEV_IDECS is not set
-CONFIG_BLK_DEV_IDECD=m
-# CONFIG_BLK_DEV_IDETAPE is not set
-CONFIG_BLK_DEV_IDEFLOPPY=y
-# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-CONFIG_BLK_DEV_ISAPNP=y
-# CONFIG_BLK_DEV_RZ1000 is not set
-CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_IDEPCI_SHARE_IRQ=y
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
-# CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_PCI_WIP is not set
-# CONFIG_BLK_DEV_IDEDMA_TIMEOUT is not set
-# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
-CONFIG_BLK_DEV_ADMA=y
-CONFIG_BLK_DEV_AEC62XX=y
-CONFIG_AEC62XX_TUNING=y
-CONFIG_BLK_DEV_ALI15X3=y
-# CONFIG_WDC_ALI15X3 is not set
-CONFIG_BLK_DEV_AMD74XX=y
-# CONFIG_AMD74XX_OVERRIDE is not set
-CONFIG_BLK_DEV_CMD64X=y
-CONFIG_BLK_DEV_CMD680=y
-CONFIG_BLK_DEV_CY82C693=y
-CONFIG_BLK_DEV_CS5530=y
-CONFIG_BLK_DEV_HPT34X=y
-# CONFIG_HPT34X_AUTODMA is not set
-CONFIG_BLK_DEV_HPT366=y
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_PIIX_TUNING=y
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_ADMA100 is not set
-CONFIG_BLK_DEV_PDC202XX=y
-# CONFIG_PDC202XX_BURST is not set
-# CONFIG_PDC202XX_FORCE is not set
-CONFIG_BLK_DEV_SVWKS=y
-CONFIG_BLK_DEV_SIS5513=y
-CONFIG_BLK_DEV_SLC90E66=y
-# CONFIG_BLK_DEV_TRM290 is not set
-CONFIG_BLK_DEV_VIA82CXXX=y
-CONFIG_BLK_DEV_CENATEK=y
-# CONFIG_IDE_CHIPSETS is not set
-# CONFIG_BLK_DEV_ELEVATOR_NOOP is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_DMA_NONPCI is not set
-CONFIG_BLK_DEV_IDE_MODES=y
-# CONFIG_BLK_DEV_ATARAID is not set
-# CONFIG_BLK_DEV_ATARAID_PDC is not set
-# CONFIG_BLK_DEV_ATARAID_HPT is not set
-
-#
-# SCSI support
-#
-CONFIG_SCSI=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_SD_EXTRA_DEVS=40
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=m
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_SR_EXTRA_DEVS=4
-CONFIG_CHR_DEV_SG=m
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_DEBUG_QUEUES is not set
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AHA1740 is not set
-# CONFIG_SCSI_AACRAID is not set
-CONFIG_SCSI_AIC7XXX=y
-CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
-CONFIG_AIC7XXX_RESET_DELAY_MS=15000
-# CONFIG_AIC7XXX_PROBE_EISA_VL is not set
-# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
-# CONFIG_SCSI_AIC79XX is not set
-CONFIG_SCSI_DPT_I2O=y
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_AM53C974 is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_DMA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_PPA is not set
-# CONFIG_SCSI_IMM is not set
-# CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_NCR53C7xx is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_NCR53C8XX is not set
-# CONFIG_SCSI_SYM53C8XX is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_NEWISP is not set
-# CONFIG_SCSI_SEAGATE is not set
-# CONFIG_SCSI_SIM710 is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_ULTRASTOR is not set
-CONFIG_SCSI_DEBUG=m
-
-#
-# Fusion MPT device support
-#
-CONFIG_FUSION=y
-CONFIG_FUSION_BOOT=y
-CONFIG_FUSION_ISENSE=m
-CONFIG_FUSION_CTL=m
-# CONFIG_FUSION_LAN is not set
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-# CONFIG_I2O_PCI is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-CONFIG_DUMMY=m
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
-# CONFIG_ETHERTAP is not set
-# CONFIG_NET_SB1000 is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_SUNLANCE is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNBMAC is not set
-# CONFIG_SUNQE is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
-# CONFIG_CS89x0 is not set
-CONFIG_TULIP=m
-# CONFIG_TC35815 is not set
-# CONFIG_TULIP_MWI is not set
-CONFIG_TULIP_MMIO=y
-CONFIG_DE4X5=m
-# CONFIG_DGRS is not set
-# CONFIG_DM9102 is not set
-CONFIG_EEPRO100=m
-CONFIG_NET_E100=m
-# CONFIG_LNE390 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_NE3210 is not set
-# CONFIG_ES3210 is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_8139TOO_PIO is not set
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-# CONFIG_8139TOO_8129 is not set
-# CONFIG_8139_NEW_RX_RESET is not set
-# CONFIG_SIS900 is not set
-# CONFIG_SIS900_OLD is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_RHINE_MMIO is not set
-# CONFIG_WINBOND_840 is not set
-# CONFIG_NET_POCKET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-CONFIG_ACENIC=m
-# CONFIG_ACENIC_OMIT_TIGON_I is not set
-# CONFIG_DL2K is not set
-# CONFIG_MYRI_SBUS is not set
-CONFIG_NS83820=m
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_SK98LIN is not set
-CONFIG_NET_BROADCOM=m
-CONFIG_TIGON3=m
-CONFIG_NET_E1000=m
-# CONFIG_FDDI is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Quadrics Supercomputers
-#
-
-#
-# QsNet
-#
-CONFIG_QUADRICS=y
-CONFIG_QSNETMOD=m
-CONFIG_ELAN3MOD=m
-CONFIG_EPMOD=m
-CONFIG_EIPMOD=m
-CONFIG_RMSMOD=m
-CONFIG_JTAG=m
-
-#
-# QsNet II
-#
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-CONFIG_KALLSYMS=y
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Input core support
-#
-# CONFIG_INPUT is not set
-# CONFIG_INPUT_KEYBDEV is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-
-#
-# Character devices
-#
-CONFIG_ECC=m
-CONFIG_CHAOSTEST=m
-CONFIG_P4THERM=m
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-CONFIG_SERIAL_EXTENDED=y
-# CONFIG_SERIAL_MANY_PORTS is not set
-CONFIG_SERIAL_SHARE_IRQ=y
-# CONFIG_SERIAL_DETECT_IRQ is not set
-# CONFIG_SERIAL_MULTIPORT is not set
-# CONFIG_HUB6 is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=2048
-# CONFIG_PRINTER is not set
-# CONFIG_PPDEV is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-CONFIG_I2C_MAINBOARD=y
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_HYDRA is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_TSUNAMI is not set
-CONFIG_I2C_I801=m
-# CONFIG_I2C_I810 is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-# CONFIG_I2C_VOODOO3 is not set
-CONFIG_I2C_ISA=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_PROC=y
-
-#
-# Hardware sensors support
-#
-CONFIG_SENSORS=y
-CONFIG_SENSORS_ADM1021=m
-# CONFIG_SENSORS_ADM1024 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_FSCSCY is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_MAXILIFE is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_MTP008 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-CONFIG_SENSORS_LM87=m
-# CONFIG_SENSORS_SIS5595 is not set
-# CONFIG_SENSORS_THMC50 is not set
-# CONFIG_SENSORS_VIA686A is not set
-CONFIG_SENSORS_W83781D=y
-# CONFIG_SENSORS_OTHER is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-CONFIG_MOUSE=y
-CONFIG_PSMOUSE=y
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
-# CONFIG_MK712_MOUSE is not set
-
-#
-# Joysticks
-#
-# CONFIG_INPUT_GAMEPORT is not set
-
-#
-# Input core support is needed for gameports
-#
-
-#
-# Input core support is needed for joysticks
-#
-# CONFIG_QIC02_TAPE is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_AMD_RNG is not set
-# CONFIG_INTEL_RNG is not set
-# CONFIG_AMD_PM768 is not set
-# CONFIG_NVRAM is not set
-CONFIG_RTC=y
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_SONYPI is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-CONFIG_AGP=m
-CONFIG_AGP_INTEL=y
-# CONFIG_AGP_I810 is not set
-# CONFIG_AGP_VIA is not set
-# CONFIG_AGP_AMD is not set
-# CONFIG_AGP_SIS is not set
-# CONFIG_AGP_ALI is not set
-# CONFIG_AGP_SWORKS is not set
-# CONFIG_DRM is not set
-# CONFIG_MWAVE is not set
-# CONFIG_BATTERY_GERICOM is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Crypto Hardware support
-#
-# CONFIG_CRYPTO is not set
-
-#
-# File systems
-#
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_ADFS_FS_RW is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BEFS_DEBUG is not set
-# CONFIG_BFS_FS is not set
-CONFIG_EXT3_FS=y
-CONFIG_JBD=y
-CONFIG_JBD_DEBUG=y
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_UMSDOS_FS=m
-CONFIG_VFAT_FS=m
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-CONFIG_CRAMFS=y
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-# CONFIG_JFS_FS is not set
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_RW is not set
-# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-CONFIG_ROMFS_FS=m
-CONFIG_EXT2_FS=y
-# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
-# CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
-
-#
-# Network File Systems
-#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-CONFIG_NFS_FS=m
-CONFIG_NFS_V3=y
-# CONFIG_ROOT_NFS is not set
-CONFIG_NFSD=m
-CONFIG_NFSD_V3=y
-CONFIG_NFSD_TCP=y
-CONFIG_SUNRPC=m
-CONFIG_LOCKD=m
-CONFIG_LOCKD_V4=y
-# CONFIG_SMB_FS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
-CONFIG_PFS_FS=m
-CONFIG_PFS_DIRECTIO=m
-CONFIG_ZISOFS_FS=y
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-CONFIG_OSF_PARTITION=y
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
-CONFIG_BSD_DISKLABEL=y
-CONFIG_MINIX_SUBPARTITION=y
-CONFIG_SOLARIS_X86_PARTITION=y
-CONFIG_UNIXWARE_DISKLABEL=y
-# CONFIG_LDM_PARTITION is not set
-CONFIG_SGI_PARTITION=y
-# CONFIG_ULTRIX_PARTITION is not set
-CONFIG_SUN_PARTITION=y
-# CONFIG_SMB_NLS is not set
-CONFIG_NLS=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-CONFIG_NLS_CODEPAGE_850=m
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-CONFIG_NLS_ISO8859_1=m
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Console drivers
-#
-CONFIG_VGA_CONSOLE=y
-CONFIG_VIDEO_SELECT=y
-# CONFIG_VIDEO_IGNORE_BAD_MODE is not set
-# CONFIG_MDA_CONSOLE is not set
-
-#
-# Frame-buffer support
-#
-# CONFIG_FB is not set
-# CONFIG_SPEAKUP is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BLUEZ is not set
-
-#
-# Kernel hacking
-#
-CONFIG_DEBUG_KERNEL=y
-CONFIG_FRAME_POINTER=y
-CONFIG_STACK_TRACE_SCAN=y
-CONFIG_STACK_TRACE_FPTR=y
-CONFIG_STACK_TRACE_PARAM_COUNT=4
-# CONFIG_DEBUG_HIGHMEM is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_IOVIRT is not set
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_MCL_COREDUMP=y
-CONFIG_BOOTIMG=y
-# CONFIG_OPROFILE is not set
-# CONFIG_NOBIGSTACK is not set
-CONFIG_STACK_SIZE_16KB=y
-# CONFIG_STACK_SIZE_32KB is not set
-# CONFIG_STACK_SIZE_64KB is not set
-CONFIG_STACK_SIZE_SHIFT=2
-
-#
-# Library routines
-#
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
+++ /dev/null
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_X86=y
-CONFIG_ISA=y
-# CONFIG_SBUS is not set
-CONFIG_UID16=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Processor type and features
-#
-CONFIG_LOLAT=y
-# CONFIG_LOLAT_SYSCTL is not set
-# CONFIG_M386 is not set
-# CONFIG_M486 is not set
-# CONFIG_M586 is not set
-# CONFIG_M586TSC is not set
-# CONFIG_M586MMX is not set
-# CONFIG_M686 is not set
-# CONFIG_MPENTIUMIII is not set
-CONFIG_MPENTIUM4=y
-# CONFIG_MK6 is not set
-# CONFIG_MK7 is not set
-# CONFIG_MELAN is not set
-# CONFIG_MCRUSOE is not set
-# CONFIG_MWINCHIPC6 is not set
-# CONFIG_MWINCHIP2 is not set
-# CONFIG_MWINCHIP3D is not set
-# CONFIG_MCYRIXIII is not set
-CONFIG_X86_WP_WORKS_OK=y
-CONFIG_X86_INVLPG=y
-CONFIG_X86_CMPXCHG=y
-CONFIG_X86_XADD=y
-CONFIG_X86_BSWAP=y
-CONFIG_X86_POPAD_OK=y
-# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_X86_L1_CACHE_SHIFT=7
-CONFIG_X86_TSC=y
-CONFIG_X86_GOOD_APIC=y
-CONFIG_X86_PGE=y
-CONFIG_X86_USE_PPRO_CHECKSUM=y
-CONFIG_X86_MCE=y
-# CONFIG_CPU_FREQ is not set
-# CONFIG_USE_IRQ_STACKS is not set
-# CONFIG_TOSHIBA is not set
-# CONFIG_I8K is not set
-CONFIG_MICROCODE=m
-CONFIG_X86_MSR=m
-CONFIG_X86_CPUID=m
-# CONFIG_E820_PROC is not set
-# CONFIG_NOHIGHMEM is not set
-CONFIG_HIGHMEM4G=y
-# CONFIG_HIGHMEM64G is not set
-CONFIG_HIGHMEM=y
-CONFIG_HIGHIO=y
-# CONFIG_MATH_EMULATION is not set
-CONFIG_MTRR=y
-CONFIG_SMP=y
-# CONFIG_MULTIQUAD is not set
-CONFIG_HAVE_DEC_LOCK=y
-
-#
-# General setup
-#
-CONFIG_HZ=100
-CONFIG_NET=y
-CONFIG_X86_IO_APIC=y
-CONFIG_X86_LOCAL_APIC=y
-CONFIG_PCI=y
-# CONFIG_PCI_GOBIOS is not set
-# CONFIG_PCI_GODIRECT is not set
-CONFIG_PCI_GOANY=y
-CONFIG_PCI_BIOS=y
-CONFIG_PCI_DIRECT=y
-CONFIG_PCI_NAMES=y
-
-#
-# Performance-monitoring counters support
-#
-CONFIG_PERFCTR=m
-CONFIG_KPERFCTR=y
-# CONFIG_PERFCTR_DEBUG is not set
-# CONFIG_PERFCTR_INIT_TESTS is not set
-CONFIG_PERFCTR_VIRTUAL=y
-CONFIG_PERFCTR_GLOBAL=y
-# CONFIG_EISA is not set
-# CONFIG_MCA is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
-# CONFIG_HOTPLUG_PCI is not set
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=m
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=m
-# CONFIG_IKCONFIG is not set
-CONFIG_PM=y
-
-#
-# Additional device driver support
-#
-# CONFIG_CIPE is not set
-# CONFIG_CRYPTO_AEP is not set
-# CONFIG_MEGARAC is not set
-CONFIG_FC_QLA2200=m
-CONFIG_FC_QLA2300=m
-# CONFIG_SCSI_ISCSI is not set
-CONFIG_IBMASM=m
-CONFIG_IBMSER=m
-CONFIG_NEW_DIGI_EPCA=m
-CONFIG_NVIDIA=m
-# CONFIG_ACPI is not set
-CONFIG_APM=y
-CONFIG_APM_IGNORE_USER_SUSPEND=y
-# CONFIG_APM_DO_ENABLE is not set
-# CONFIG_APM_CPU_IDLE is not set
-# CONFIG_APM_DISPLAY_BLANK is not set
-CONFIG_APM_RTC_IS_GMT=y
-# CONFIG_APM_ALLOW_INTS is not set
-# CONFIG_APM_REAL_MODE_POWER_OFF is not set
-
-#
-# Binary emulation of other systems
-#
-# CONFIG_ABI is not set
-# CONFIG_ABI_SVR4 is not set
-
-#
-# Support for foreign binary formats
-#
-# CONFIG_BINFMT_COFF is not set
-# CONFIG_BINFMT_XOUT is not set
-# CONFIG_BINFMT_XOUT_X286 is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_PARTITIONS is not set
-# CONFIG_MTD_CONCAT is not set
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=m
-# CONFIG_MTD_BLOCK is not set
-# CONFIG_MTD_BLOCK_RO is not set
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-# CONFIG_MTD_CFI is not set
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_GEN_PROBE=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_NOSWAP=y
-# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-CONFIG_MTD_CFI_GEOMETRY=y
-CONFIG_MTD_CFI_B1=y
-# CONFIG_MTD_CFI_B2 is not set
-# CONFIG_MTD_CFI_B4 is not set
-# CONFIG_MTD_CFI_B8 is not set
-CONFIG_MTD_CFI_I1=y
-# CONFIG_MTD_CFI_I2 is not set
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_AMDSTD=y
-# CONFIG_MTD_RAM is not set
-CONFIG_MTD_ROM=y
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-# CONFIG_MTD_AMDSTD is not set
-# CONFIG_MTD_SHARP is not set
-# CONFIG_MTD_JEDEC is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_PHYSMAP is not set
-# CONFIG_MTD_PNC2000 is not set
-# CONFIG_MTD_SC520CDP is not set
-# CONFIG_MTD_NETSC520 is not set
-# CONFIG_MTD_SBC_GXX is not set
-# CONFIG_MTD_ELAN_104NC is not set
-# CONFIG_MTD_DILNETPC is not set
-# CONFIG_MTD_MIXMEM is not set
-# CONFIG_MTD_OCTAGON is not set
-# CONFIG_MTD_VMAX is not set
-# CONFIG_MTD_L440GX is not set
-# CONFIG_MTD_AMD766ROM is not set
-CONFIG_MTD_ICH2ROM=m
-# CONFIG_MTD_PCI is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC1000 is not set
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOCPROBE is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Parallel port support
-#
-CONFIG_PARPORT=m
-CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_CML1=m
-# CONFIG_PARPORT_SERIAL is not set
-# CONFIG_PARPORT_PC_FIFO is not set
-# CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_AMIGA is not set
-# CONFIG_PARPORT_MFC3 is not set
-# CONFIG_PARPORT_ATARI is not set
-# CONFIG_PARPORT_GSC is not set
-# CONFIG_PARPORT_SUNBPP is not set
-# CONFIG_PARPORT_OTHER is not set
-CONFIG_PARPORT_1284=y
-
-#
-# Plug and Play configuration
-#
-CONFIG_PNP=y
-CONFIG_ISAPNP=y
-# CONFIG_PNPBIOS is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_FD=y
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_CISS_SCSI_TAPE is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_NBD=m
-# CONFIG_BLK_DEV_ENBD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-
-#
-# Multi-device support (RAID and LVM)
-#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-CONFIG_BLK_DEV_LVM=m
-
-#
-# Cryptography support (CryptoAPI)
-#
-# CONFIG_CRYPTO is not set
-# CONFIG_CIPHERS is not set
-# CONFIG_CRYPTODEV is not set
-# CONFIG_CRYPTOLOOP is not set
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_FILTER=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_TUX is not set
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_FWMARK=y
-CONFIG_IP_ROUTE_NAT=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_TOS=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_ROUTE_LARGE_TABLES=y
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-CONFIG_SYN_COOKIES=y
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-# CONFIG_IP_NF_FTP is not set
-# CONFIG_IP_NF_IRC is not set
-# CONFIG_IP_NF_QUEUE is not set
-CONFIG_IP_NF_IPTABLES=m
-# CONFIG_IP_NF_MATCH_LIMIT is not set
-# CONFIG_IP_NF_MATCH_MAC is not set
-# CONFIG_IP_NF_MATCH_MARK is not set
-# CONFIG_IP_NF_MATCH_MULTIPORT is not set
-# CONFIG_IP_NF_MATCH_TOS is not set
-# CONFIG_IP_NF_MATCH_AH_ESP is not set
-# CONFIG_IP_NF_MATCH_LENGTH is not set
-# CONFIG_IP_NF_MATCH_TTL is not set
-# CONFIG_IP_NF_MATCH_TCPMSS is not set
-CONFIG_IP_NF_MATCH_STATE=m
-# CONFIG_IP_NF_MATCH_UNCLEAN is not set
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_FILTER=m
-# CONFIG_IP_NF_TARGET_REJECT is not set
-# CONFIG_IP_NF_TARGET_MIRROR is not set
-# CONFIG_IP_NF_NAT is not set
-# CONFIG_IP_NF_MANGLE is not set
-CONFIG_IP_NF_TARGET_LOG=m
-# CONFIG_IP_NF_TARGET_ULOG is not set
-# CONFIG_IP_NF_TARGET_TCPMSS is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_KHTTPD=m
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-
-#
-#
-#
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-
-#
-# Appletalk devices
-#
-# CONFIG_DEV_APPLETALK is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-CONFIG_NET_PKTGEN=m
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-# CONFIG_PHONE_IXJ is not set
-# CONFIG_PHONE_IXJ_PCMCIA is not set
-
-#
-# ATA/IDE/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_IDEDISK_MULTI_MODE=y
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
-# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
-# CONFIG_BLK_DEV_IDEDISK_IBM is not set
-# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
-# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
-# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
-# CONFIG_BLK_DEV_IDEDISK_WD is not set
-# CONFIG_BLK_DEV_COMMERIAL is not set
-# CONFIG_BLK_DEV_TIVO is not set
-# CONFIG_BLK_DEV_IDECS is not set
-CONFIG_BLK_DEV_IDECD=m
-# CONFIG_BLK_DEV_IDETAPE is not set
-CONFIG_BLK_DEV_IDEFLOPPY=y
-# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-CONFIG_BLK_DEV_ISAPNP=y
-# CONFIG_BLK_DEV_RZ1000 is not set
-CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_IDEPCI_SHARE_IRQ=y
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
-# CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_PCI_WIP is not set
-# CONFIG_BLK_DEV_IDEDMA_TIMEOUT is not set
-# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
-CONFIG_BLK_DEV_ADMA=y
-CONFIG_BLK_DEV_AEC62XX=y
-CONFIG_AEC62XX_TUNING=y
-CONFIG_BLK_DEV_ALI15X3=y
-# CONFIG_WDC_ALI15X3 is not set
-CONFIG_BLK_DEV_AMD74XX=y
-# CONFIG_AMD74XX_OVERRIDE is not set
-CONFIG_BLK_DEV_CMD64X=y
-CONFIG_BLK_DEV_CMD680=y
-CONFIG_BLK_DEV_CY82C693=y
-CONFIG_BLK_DEV_CS5530=y
-CONFIG_BLK_DEV_HPT34X=y
-# CONFIG_HPT34X_AUTODMA is not set
-CONFIG_BLK_DEV_HPT366=y
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_PIIX_TUNING=y
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_ADMA100 is not set
-CONFIG_BLK_DEV_PDC202XX=y
-# CONFIG_PDC202XX_BURST is not set
-# CONFIG_PDC202XX_FORCE is not set
-CONFIG_BLK_DEV_SVWKS=y
-CONFIG_BLK_DEV_SIS5513=y
-CONFIG_BLK_DEV_SLC90E66=y
-# CONFIG_BLK_DEV_TRM290 is not set
-CONFIG_BLK_DEV_VIA82CXXX=y
-CONFIG_BLK_DEV_CENATEK=y
-# CONFIG_IDE_CHIPSETS is not set
-# CONFIG_BLK_DEV_ELEVATOR_NOOP is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_DMA_NONPCI is not set
-CONFIG_BLK_DEV_IDE_MODES=y
-# CONFIG_BLK_DEV_ATARAID is not set
-# CONFIG_BLK_DEV_ATARAID_PDC is not set
-# CONFIG_BLK_DEV_ATARAID_HPT is not set
-
-#
-# SCSI support
-#
-CONFIG_SCSI=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_SD_EXTRA_DEVS=40
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=m
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_SR_EXTRA_DEVS=4
-CONFIG_CHR_DEV_SG=m
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_DEBUG_QUEUES is not set
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AHA1740 is not set
-# CONFIG_SCSI_AACRAID is not set
-CONFIG_SCSI_AIC7XXX=y
-CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
-CONFIG_AIC7XXX_RESET_DELAY_MS=15000
-# CONFIG_AIC7XXX_PROBE_EISA_VL is not set
-# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
-# CONFIG_SCSI_AIC79XX is not set
-CONFIG_SCSI_DPT_I2O=y
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_AM53C974 is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_DMA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_PPA is not set
-# CONFIG_SCSI_IMM is not set
-# CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_NCR53C7xx is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_NCR53C8XX is not set
-# CONFIG_SCSI_SYM53C8XX is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_NEWISP is not set
-# CONFIG_SCSI_SEAGATE is not set
-# CONFIG_SCSI_SIM710 is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_ULTRASTOR is not set
-CONFIG_SCSI_DEBUG=m
-
-#
-# Fusion MPT device support
-#
-CONFIG_FUSION=y
-CONFIG_FUSION_BOOT=y
-CONFIG_FUSION_ISENSE=m
-CONFIG_FUSION_CTL=m
-# CONFIG_FUSION_LAN is not set
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-# CONFIG_I2O_PCI is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-CONFIG_DUMMY=m
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
-# CONFIG_ETHERTAP is not set
-# CONFIG_NET_SB1000 is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_SUNLANCE is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNBMAC is not set
-# CONFIG_SUNQE is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
-# CONFIG_CS89x0 is not set
-CONFIG_TULIP=m
-# CONFIG_TC35815 is not set
-# CONFIG_TULIP_MWI is not set
-CONFIG_TULIP_MMIO=y
-CONFIG_DE4X5=m
-# CONFIG_DGRS is not set
-# CONFIG_DM9102 is not set
-CONFIG_EEPRO100=m
-CONFIG_NET_E100=m
-# CONFIG_LNE390 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_NE3210 is not set
-# CONFIG_ES3210 is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_8139TOO_PIO is not set
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-# CONFIG_8139TOO_8129 is not set
-# CONFIG_8139_NEW_RX_RESET is not set
-# CONFIG_SIS900 is not set
-# CONFIG_SIS900_OLD is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_RHINE_MMIO is not set
-# CONFIG_WINBOND_840 is not set
-# CONFIG_NET_POCKET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-CONFIG_ACENIC=m
-# CONFIG_ACENIC_OMIT_TIGON_I is not set
-# CONFIG_DL2K is not set
-# CONFIG_MYRI_SBUS is not set
-CONFIG_NS83820=m
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_SK98LIN is not set
-CONFIG_NET_BROADCOM=m
-CONFIG_TIGON3=m
-CONFIG_NET_E1000=m
-# CONFIG_FDDI is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Quadrics Supercomputers
-#
-
-#
-# QsNet
-#
-CONFIG_QUADRICS=y
-CONFIG_QSNETMOD=m
-CONFIG_ELAN3MOD=m
-CONFIG_EPMOD=m
-CONFIG_EIPMOD=m
-CONFIG_RMSMOD=m
-CONFIG_JTAG=m
-
-#
-# QsNet II
-#
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-CONFIG_KALLSYMS=y
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Input core support
-#
-# CONFIG_INPUT is not set
-# CONFIG_INPUT_KEYBDEV is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-
-#
-# Character devices
-#
-CONFIG_ECC=m
-CONFIG_CHAOSTEST=m
-CONFIG_P4THERM=m
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-CONFIG_SERIAL_EXTENDED=y
-# CONFIG_SERIAL_MANY_PORTS is not set
-CONFIG_SERIAL_SHARE_IRQ=y
-# CONFIG_SERIAL_DETECT_IRQ is not set
-# CONFIG_SERIAL_MULTIPORT is not set
-# CONFIG_HUB6 is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=2048
-# CONFIG_PRINTER is not set
-# CONFIG_PPDEV is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-CONFIG_I2C_MAINBOARD=y
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_HYDRA is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_TSUNAMI is not set
-CONFIG_I2C_I801=m
-# CONFIG_I2C_I810 is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-# CONFIG_I2C_VOODOO3 is not set
-CONFIG_I2C_ISA=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_PROC=y
-
-#
-# Hardware sensors support
-#
-CONFIG_SENSORS=y
-CONFIG_SENSORS_ADM1021=m
-# CONFIG_SENSORS_ADM1024 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_FSCSCY is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_MAXILIFE is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_MTP008 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-CONFIG_SENSORS_LM87=m
-# CONFIG_SENSORS_SIS5595 is not set
-# CONFIG_SENSORS_THMC50 is not set
-# CONFIG_SENSORS_VIA686A is not set
-CONFIG_SENSORS_W83781D=y
-# CONFIG_SENSORS_OTHER is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-CONFIG_MOUSE=y
-CONFIG_PSMOUSE=y
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
-# CONFIG_MK712_MOUSE is not set
-
-#
-# Joysticks
-#
-# CONFIG_INPUT_GAMEPORT is not set
-
-#
-# Input core support is needed for gameports
-#
-
-#
-# Input core support is needed for joysticks
-#
-# CONFIG_QIC02_TAPE is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_AMD_RNG is not set
-# CONFIG_INTEL_RNG is not set
-# CONFIG_AMD_PM768 is not set
-# CONFIG_NVRAM is not set
-CONFIG_RTC=y
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_SONYPI is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-CONFIG_AGP=m
-CONFIG_AGP_INTEL=y
-# CONFIG_AGP_I810 is not set
-# CONFIG_AGP_VIA is not set
-# CONFIG_AGP_AMD is not set
-# CONFIG_AGP_SIS is not set
-# CONFIG_AGP_ALI is not set
-# CONFIG_AGP_SWORKS is not set
-# CONFIG_DRM is not set
-# CONFIG_MWAVE is not set
-# CONFIG_BATTERY_GERICOM is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Crypto Hardware support
-#
-# CONFIG_CRYPTO is not set
-
-#
-# File systems
-#
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_ADFS_FS_RW is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BEFS_DEBUG is not set
-# CONFIG_BFS_FS is not set
-CONFIG_EXT3_FS=y
-CONFIG_JBD=y
-CONFIG_JBD_DEBUG=y
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_UMSDOS_FS=m
-CONFIG_VFAT_FS=m
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-CONFIG_CRAMFS=y
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-# CONFIG_JFS_FS is not set
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_RW is not set
-# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-CONFIG_ROMFS_FS=m
-CONFIG_EXT2_FS=y
-# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
-# CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
-
-#
-# Network File Systems
-#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-CONFIG_NFS_FS=m
-CONFIG_NFS_V3=y
-# CONFIG_ROOT_NFS is not set
-CONFIG_NFSD=m
-CONFIG_NFSD_V3=y
-CONFIG_NFSD_TCP=y
-CONFIG_SUNRPC=m
-CONFIG_LOCKD=m
-CONFIG_LOCKD_V4=y
-# CONFIG_SMB_FS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
-CONFIG_PFS_FS=m
-CONFIG_PFS_DIRECTIO=m
-CONFIG_ZISOFS_FS=y
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-CONFIG_OSF_PARTITION=y
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
-CONFIG_BSD_DISKLABEL=y
-CONFIG_MINIX_SUBPARTITION=y
-CONFIG_SOLARIS_X86_PARTITION=y
-CONFIG_UNIXWARE_DISKLABEL=y
-# CONFIG_LDM_PARTITION is not set
-CONFIG_SGI_PARTITION=y
-# CONFIG_ULTRIX_PARTITION is not set
-CONFIG_SUN_PARTITION=y
-# CONFIG_SMB_NLS is not set
-CONFIG_NLS=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-CONFIG_NLS_CODEPAGE_850=m
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-CONFIG_NLS_ISO8859_1=m
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Console drivers
-#
-CONFIG_VGA_CONSOLE=y
-CONFIG_VIDEO_SELECT=y
-# CONFIG_VIDEO_IGNORE_BAD_MODE is not set
-# CONFIG_MDA_CONSOLE is not set
-
-#
-# Frame-buffer support
-#
-# CONFIG_FB is not set
-# CONFIG_SPEAKUP is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BLUEZ is not set
-
-#
-# Kernel hacking
-#
-CONFIG_DEBUG_KERNEL=y
-CONFIG_FRAME_POINTER=y
-CONFIG_STACK_TRACE_SCAN=y
-CONFIG_STACK_TRACE_FPTR=y
-CONFIG_STACK_TRACE_PARAM_COUNT=4
-# CONFIG_DEBUG_HIGHMEM is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_IOVIRT is not set
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_MCL_COREDUMP=y
-CONFIG_BOOTIMG=y
-# CONFIG_OPROFILE is not set
-# CONFIG_NOBIGSTACK is not set
-CONFIG_STACK_SIZE_16KB=y
-# CONFIG_STACK_SIZE_32KB is not set
-# CONFIG_STACK_SIZE_64KB is not set
-CONFIG_STACK_SIZE_SHIFT=2
-
-#
-# Library routines
-#
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
+++ /dev/null
-#
-# Automatically generated make config: don't edit
-#
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# General setup
-#
-CONFIG_IA64=y
-# CONFIG_ISA is not set
-# CONFIG_EISA is not set
-# CONFIG_MCA is not set
-# CONFIG_SBUS is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-# CONFIG_ITANIUM is not set
-CONFIG_MCKINLEY=y
-# CONFIG_IA64_GENERIC is not set
-# CONFIG_IA64_DIG is not set
-# CONFIG_IA64_HP_SIM is not set
-CONFIG_IA64_HP_ZX1=y
-# CONFIG_IA64_SGI_SN1 is not set
-# CONFIG_IA64_SGI_SN2 is not set
-# CONFIG_IA64_PAGE_SIZE_4KB is not set
-CONFIG_IA64_PAGE_SIZE_8KB=y
-# CONFIG_IA64_PAGE_SIZE_16KB is not set
-# CONFIG_IA64_PAGE_SIZE_64KB is not set
-CONFIG_IA64_L1_CACHE_SHIFT=7
-CONFIG_IA64_MCA=y
-CONFIG_PM=y
-CONFIG_KCORE_ELF=y
-CONFIG_IA64_PAL_IDLE=y
-CONFIG_SMP=y
-CONFIG_IA32_SUPPORT=y
-CONFIG_PERFMON=y
-CONFIG_IA64_PALINFO=y
-CONFIG_EFI_VARS=y
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=m
-
-#
-# Misc devices
-#
-# CONFIG_BMC is not set
-CONFIG_ACPI=y
-CONFIG_ACPI_EFI=y
-CONFIG_ACPI_INTERPRETER=y
-CONFIG_ACPI_KERNEL_CONFIG=y
-
-#
-# ACPI Support
-#
-CONFIG_ACPI_PCI=y
-CONFIG_ACPI=y
-CONFIG_ACPI_EFI=y
-CONFIG_ACPI_BOOT=y
-CONFIG_ACPI_BUS=y
-CONFIG_ACPI_INTERPRETER=y
-CONFIG_ACPI_POWER=y
-CONFIG_ACPI_SYSTEM=y
-CONFIG_ACPI_BUTTON=y
-CONFIG_ACPI_FAN=y
-CONFIG_ACPI_PROCESSOR=y
-CONFIG_ACPI_THERMAL=y
-# CONFIG_ACPI_DEBUG is not set
-CONFIG_PCI=y
-CONFIG_PCI_NAMES=y
-CONFIG_HOTPLUG=y
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-# CONFIG_HOTPLUG_PCI_COMPAQ is not set
-# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
-# CONFIG_HOTPLUG_PCI_ACPI is not set
-
-#
-# PCMCIA/CardBus support
-#
-# CONFIG_PCMCIA is not set
-
-#
-# Parallel port support
-#
-CONFIG_PARPORT=m
-CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_CML1=m
-CONFIG_PARPORT_SERIAL=m
-# CONFIG_PARPORT_PC_FIFO is not set
-# CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_AMIGA is not set
-# CONFIG_PARPORT_MFC3 is not set
-# CONFIG_PARPORT_ATARI is not set
-# CONFIG_PARPORT_GSC is not set
-# CONFIG_PARPORT_SUNBPP is not set
-# CONFIG_PARPORT_OTHER is not set
-CONFIG_PARPORT_1284=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=m
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_FILTER=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_FWMARK=y
-CONFIG_IP_ROUTE_NAT=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_TOS=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_ROUTE_LARGE_TABLES=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-CONFIG_NET_IPIP=m
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-CONFIG_SYN_COOKIES=y
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-# CONFIG_IP_NF_MATCH_AH_ESP is not set
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_UNCLEAN=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_MIRROR=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-# CONFIG_IP_NF_NAT_LOCAL is not set
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_LOG=m
-# CONFIG_IP_NF_TARGET_ULOG is not set
-CONFIG_IP_NF_TARGET_TCPMSS=m
-# CONFIG_IP_NF_ARPTABLES is not set
-# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-
-#
-# IP: Virtual Server Configuration
-#
-CONFIG_IP_VS=m
-# CONFIG_IP_VS_DEBUG is not set
-CONFIG_IP_VS_TAB_BITS=12
-
-#
-# IPVS scheduler
-#
-CONFIG_IP_VS_RR=m
-CONFIG_IP_VS_WRR=m
-CONFIG_IP_VS_LC=m
-CONFIG_IP_VS_WLC=m
-CONFIG_IP_VS_LBLC=m
-CONFIG_IP_VS_LBLCR=m
-CONFIG_IP_VS_DH=m
-CONFIG_IP_VS_SH=m
-
-#
-# IPVS application helper
-#
-CONFIG_IP_VS_FTP=m
-# CONFIG_IPV6 is not set
-# CONFIG_KHTTPD is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-
-#
-#
-#
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-
-#
-# Appletalk devices
-#
-# CONFIG_DEV_APPLETALK is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Plug and Play configuration
-#
-# CONFIG_PNP is not set
-# CONFIG_ISAPNP is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_CISS_SCSI_TAPE is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_NBD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=65536
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_BLK_STATS is not set
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-# CONFIG_I2O_PCI is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=y
-CONFIG_MD_RAID0=y
-CONFIG_MD_RAID1=y
-CONFIG_MD_RAID5=y
-CONFIG_MD_MULTIPATH=y
-CONFIG_BLK_DEV_LVM=y
-
-#
-# Fusion MPT device support
-#
-CONFIG_FUSION=y
-CONFIG_FUSION_BOOT=y
-CONFIG_FUSION_MAX_SGE=40
-CONFIG_FUSION_ISENSE=m
-CONFIG_FUSION_CTL=m
-CONFIG_FUSION_LAN=m
-CONFIG_NET_FC=y
-
-#
-# ATA/IDE/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
-# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
-# CONFIG_BLK_DEV_IDEDISK_IBM is not set
-# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
-# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
-# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
-# CONFIG_BLK_DEV_IDEDISK_WD is not set
-# CONFIG_BLK_DEV_COMMERIAL is not set
-# CONFIG_BLK_DEV_TIVO is not set
-# CONFIG_BLK_DEV_IDECS is not set
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDETAPE is not set
-CONFIG_BLK_DEV_IDEFLOPPY=y
-CONFIG_BLK_DEV_IDESCSI=y
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-# CONFIG_BLK_DEV_ISAPNP is not set
-# CONFIG_BLK_DEV_RZ1000 is not set
-CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_IDEPCI_SHARE_IRQ=y
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
-# CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_PCI_WIP is not set
-# CONFIG_BLK_DEV_IDEDMA_TIMEOUT is not set
-# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
-CONFIG_BLK_DEV_ADMA=y
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_AEC62XX_TUNING is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_WDC_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-# CONFIG_AMD74XX_OVERRIDE is not set
-CONFIG_BLK_DEV_CMD64X=y
-# CONFIG_BLK_DEV_CMD680 is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_HPT34X_AUTODMA is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_PIIX_TUNING=y
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_PDC202XX is not set
-# CONFIG_PDC202XX_BURST is not set
-# CONFIG_PDC202XX_FORCE is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIS5513 is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX is not set
-# CONFIG_IDE_CHIPSETS is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_DMA_NONPCI is not set
-CONFIG_BLK_DEV_IDE_MODES=y
-# CONFIG_BLK_DEV_ATARAID is not set
-# CONFIG_BLK_DEV_ATARAID_PDC is not set
-# CONFIG_BLK_DEV_ATARAID_HPT is not set
-
-#
-# SCSI support
-#
-CONFIG_SCSI=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_SD_EXTRA_DEVS=40
-CONFIG_CHR_DEV_ST=y
-CONFIG_CHR_DEV_OSST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_SR_EXTRA_DEVS=2
-CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_DEBUG_QUEUES is not set
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AHA1740 is not set
-CONFIG_SCSI_AACRAID=m
-CONFIG_SCSI_AIC7XXX=y
-CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
-CONFIG_AIC7XXX_RESET_DELAY_MS=15000
-# CONFIG_AIC7XXX_PROBE_EISA_VL is not set
-# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_AM53C974 is not set
-CONFIG_SCSI_MEGARAID=y
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_DMA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_PPA is not set
-# CONFIG_SCSI_IMM is not set
-# CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_NCR53C7xx is not set
-CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
-CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
-CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLOGIC_QLA2XXX=y
-CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2100=m
-CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2200=m
-CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2300=m
-# CONFIG_SCSI_SIM710 is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_DEBUG is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-CONFIG_DUMMY=m
-CONFIG_BONDING=m
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_SUNLANCE is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNBMAC is not set
-# CONFIG_SUNQE is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_APRICOT is not set
-# CONFIG_CS89x0 is not set
-# CONFIG_TULIP is not set
-# CONFIG_DE4X5 is not set
-# CONFIG_DGRS is not set
-# CONFIG_DM9102 is not set
-CONFIG_EEPRO100=y
-# CONFIG_E100 is not set
-# CONFIG_LNE390 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_NE3210 is not set
-# CONFIG_ES3210 is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_8139TOO_PIO is not set
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-# CONFIG_8139TOO_8129 is not set
-# CONFIG_8139_OLD_RX_RESET is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_SUNDANCE_MMIO is not set
-# CONFIG_TLAN is not set
-# CONFIG_TC35815 is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_RHINE_MMIO is not set
-# CONFIG_WINBOND_840 is not set
-# CONFIG_NET_POCKET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-CONFIG_ACENIC=m
-CONFIG_ACENIC_OMIT_TIGON_I=y
-# CONFIG_DL2K is not set
-CONFIG_E1000=y
-# CONFIG_MYRI_SBUS is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_SK98LIN is not set
-CONFIG_TIGON3=y
-
-#
-# Quadrics QsNet
-#
-CONFIG_QSNET=m
-CONFIG_ELAN3=m
-CONFIG_EP3=m
-CONFIG_EIP=m
-CONFIG_ELAN4=m
-CONFIG_RMS=m
-CONFIG_JTAG=m
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-CONFIG_NET_FC=y
-CONFIG_IPHASE5526=m
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Input core support
-#
-CONFIG_INPUT=y
-CONFIG_INPUT_KEYBDEV=y
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-CONFIG_INPUT_JOYDEV=m
-CONFIG_INPUT_EVDEV=m
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-CONFIG_SERIAL_HCDP=y
-CONFIG_SERIAL_EXTENDED=y
-CONFIG_SERIAL_ACPI=y
-CONFIG_SERIAL_MANY_PORTS=y
-CONFIG_SERIAL_SHARE_IRQ=y
-# CONFIG_SERIAL_DETECT_IRQ is not set
-CONFIG_SERIAL_MULTIPORT=y
-# CONFIG_HUB6 is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-# CONFIG_PRINTER is not set
-# CONFIG_PPDEV is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=m
-CONFIG_I2C_ALGOBIT=m
-# CONFIG_I2C_PHILIPSPAR is not set
-# CONFIG_I2C_ELV is not set
-# CONFIG_I2C_VELLEMAN is not set
-# CONFIG_I2C_ALGOPCF is not set
-CONFIG_I2C_CHARDEV=m
-CONFIG_I2C_PROC=m
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_MOUSE is not set
-
-#
-# Joysticks
-#
-# CONFIG_INPUT_GAMEPORT is not set
-# CONFIG_INPUT_NS558 is not set
-# CONFIG_INPUT_LIGHTNING is not set
-# CONFIG_INPUT_PCIGAME is not set
-# CONFIG_INPUT_CS461X is not set
-# CONFIG_INPUT_EMU10K1 is not set
-# CONFIG_INPUT_SERIO is not set
-# CONFIG_INPUT_SERPORT is not set
-
-#
-# Joysticks
-#
-# CONFIG_INPUT_ANALOG is not set
-# CONFIG_INPUT_A3D is not set
-# CONFIG_INPUT_ADI is not set
-# CONFIG_INPUT_COBRA is not set
-# CONFIG_INPUT_GF2K is not set
-# CONFIG_INPUT_GRIP is not set
-# CONFIG_INPUT_INTERACT is not set
-# CONFIG_INPUT_TMDC is not set
-# CONFIG_INPUT_SIDEWINDER is not set
-# CONFIG_INPUT_IFORCE_USB is not set
-# CONFIG_INPUT_IFORCE_232 is not set
-# CONFIG_INPUT_WARRIOR is not set
-# CONFIG_INPUT_MAGELLAN is not set
-# CONFIG_INPUT_SPACEORB is not set
-# CONFIG_INPUT_SPACEBALL is not set
-# CONFIG_INPUT_STINGER is not set
-# CONFIG_INPUT_DB9 is not set
-# CONFIG_INPUT_GAMECON is not set
-# CONFIG_INPUT_TURBOGRAFX is not set
-# CONFIG_QIC02_TAPE is not set
-CONFIG_IPMI_HANDLER=m
-CONFIG_IPMI_PANIC_EVENT=y
-CONFIG_IPMI_DEVICE_INTERFACE=m
-CONFIG_IPMI_KCS=m
-CONFIG_IPMI_WATCHDOG=m
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_INTEL_RNG is not set
-# CONFIG_AMD_PM768 is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-CONFIG_EFI_RTC=y
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# File systems
-#
-# CONFIG_QUOTA is not set
-# CONFIG_QFMT_V1 is not set
-# CONFIG_QFMT_V2 is not set
-# CONFIG_QIFACE_COMPAT is not set
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_ADFS_FS is not set
-# CONFIG_ADFS_FS_RW is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BEFS_DEBUG is not set
-# CONFIG_BFS_FS is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-CONFIG_EXT3_FS_XATTR_SHARING=y
-CONFIG_EXT3_FS_XATTR_USER=y
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-# CONFIG_UMSDOS_FS is not set
-CONFIG_VFAT_FS=y
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-CONFIG_CRAMFS=y
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-# CONFIG_ZISOFS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_RW is not set
-# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_XATTR_SHARING=y
-CONFIG_EXT2_FS_XATTR_USER=y
-# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
-# CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
-CONFIG_XFS_FS=y
-# CONFIG_XFS_POSIX_ACL is not set
-CONFIG_XFS_RT=y
-# CONFIG_XFS_QUOTA is not set
-CONFIG_XFS_DMAPI=y
-# CONFIG_XFS_DEBUG is not set
-CONFIG_PAGEBUF_DEBUG=y
-
-#
-# Network File Systems
-#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_TCP is not set
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
-CONFIG_SMB_NLS_REMOTE="cp437"
-# CONFIG_NCP_FS is not set
-# CONFIG_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
-# CONFIG_ZISOFS_FS is not set
-CONFIG_FS_MBCACHE=y
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-CONFIG_EFI_PARTITION=y
-CONFIG_SMB_NLS=y
-CONFIG_NLS=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-# CONFIG_NLS_CODEPAGE_1250 is not set
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=m
-
-#
-# Console drivers
-#
-CONFIG_VGA_CONSOLE=y
-
-#
-# Frame-buffer support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-CONFIG_USB=y
-# CONFIG_USB_DEBUG is not set
-
-#
-# Miscellaneous USB options
-#
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
-# CONFIG_USB_LONG_TIMEOUT is not set
-
-#
-# USB Host Controller Drivers
-#
-# CONFIG_USB_EHCI_HCD is not set
-CONFIG_USB_UHCI_ALT=y
-CONFIG_USB_OHCI=y
-
-#
-# USB Device Class drivers
-#
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_BLUETOOTH is not set
-# CONFIG_USB_MIDI is not set
-# CONFIG_USB_STORAGE is not set
-# CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_DATAFAB is not set
-# CONFIG_USB_STORAGE_FREECOM is not set
-# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_HP8200e is not set
-# CONFIG_USB_STORAGE_SDDR09 is not set
-# CONFIG_USB_STORAGE_SDDR55 is not set
-# CONFIG_USB_STORAGE_JUMPSHOT is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
-
-#
-# USB Human Interface Devices (HID)
-#
-CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT is not set
-# CONFIG_USB_HIDDEV is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_DC2XX is not set
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_SCANNER is not set
-# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
-
-#
-# USB Multimedia devices
-#
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
-# USB Network adaptors
-#
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_CDCETHER is not set
-# CONFIG_USB_USBNET is not set
-
-#
-# USB port drivers
-#
-# CONFIG_USB_USS720 is not set
-
-#
-# USB Serial Converter support
-#
-# CONFIG_USB_SERIAL is not set
-
-#
-# USB Miscellaneous drivers
-#
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_AUERSWALD is not set
-# CONFIG_USB_TIGL is not set
-# CONFIG_USB_BRLVGER is not set
-# CONFIG_USB_LCD is not set
-
-#
-# Library routines
-#
-CONFIG_ZLIB_INFLATE=y
-# CONFIG_ZLIB_DEFLATE is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BLUEZ is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_IA64_GRANULE_16MB is not set
-CONFIG_IA64_GRANULE_64MB=y
-CONFIG_DUMP=m
-CONFIG_DUMP_COMPRESS_RLE=m
-CONFIG_DUMP_COMPRESS_GZIP=m
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_IA64_PRINT_HAZARDS is not set
-# CONFIG_DISABLE_VHPT is not set
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_IA64_EARLY_PRINTK=y
-CONFIG_IA64_EARLY_PRINTK_UART=y
-CONFIG_IA64_EARLY_PRINTK_UART_BASE=0
-# CONFIG_IA64_EARLY_PRINTK_VGA is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_IA64_DEBUG_CMPXCHG is not set
-# CONFIG_IA64_DEBUG_IRQ is not set
-CONFIG_KALLSYMS=y
+++ /dev/null
-#
-# Automatically generated make config: don't edit
-#
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# General setup
-#
-CONFIG_IA64=y
-# CONFIG_ISA is not set
-# CONFIG_EISA is not set
-# CONFIG_MCA is not set
-# CONFIG_SBUS is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-# CONFIG_ITANIUM is not set
-CONFIG_MCKINLEY=y
-# CONFIG_IA64_GENERIC is not set
-# CONFIG_IA64_DIG is not set
-# CONFIG_IA64_HP_SIM is not set
-CONFIG_IA64_HP_ZX1=y
-# CONFIG_IA64_SGI_SN1 is not set
-# CONFIG_IA64_SGI_SN2 is not set
-# CONFIG_IA64_PAGE_SIZE_4KB is not set
-CONFIG_IA64_PAGE_SIZE_8KB=y
-# CONFIG_IA64_PAGE_SIZE_16KB=y
-# CONFIG_IA64_PAGE_SIZE_64KB is not set
-CONFIG_IA64_L1_CACHE_SHIFT=7
-CONFIG_IA64_MCA=y
-CONFIG_PM=y
-CONFIG_KCORE_ELF=y
-CONFIG_IA64_PAL_IDLE=y
-# CONFIG_SMP is not set
-CONFIG_IA32_SUPPORT=y
-CONFIG_PERFMON=y
-CONFIG_IA64_PALINFO=y
-CONFIG_EFI_VARS=y
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=m
-
-#
-# Misc devices
-#
-# CONFIG_BMC is not set
-CONFIG_ACPI=y
-CONFIG_ACPI_EFI=y
-CONFIG_ACPI_INTERPRETER=y
-CONFIG_ACPI_KERNEL_CONFIG=y
-
-#
-# ACPI Support
-#
-CONFIG_ACPI_PCI=y
-CONFIG_ACPI=y
-CONFIG_ACPI_EFI=y
-CONFIG_ACPI_BOOT=y
-CONFIG_ACPI_BUS=y
-CONFIG_ACPI_INTERPRETER=y
-CONFIG_ACPI_POWER=y
-CONFIG_ACPI_SYSTEM=y
-CONFIG_ACPI_BUTTON=y
-CONFIG_ACPI_FAN=y
-CONFIG_ACPI_PROCESSOR=y
-CONFIG_ACPI_THERMAL=y
-# CONFIG_ACPI_DEBUG is not set
-CONFIG_PCI=y
-CONFIG_PCI_NAMES=y
-CONFIG_HOTPLUG=y
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-# CONFIG_HOTPLUG_PCI_COMPAQ is not set
-# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
-# CONFIG_HOTPLUG_PCI_ACPI is not set
-
-#
-# PCMCIA/CardBus support
-#
-# CONFIG_PCMCIA is not set
-
-#
-# Parallel port support
-#
-CONFIG_PARPORT=m
-CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_CML1=m
-CONFIG_PARPORT_SERIAL=m
-# CONFIG_PARPORT_PC_FIFO is not set
-# CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_AMIGA is not set
-# CONFIG_PARPORT_MFC3 is not set
-# CONFIG_PARPORT_ATARI is not set
-# CONFIG_PARPORT_GSC is not set
-# CONFIG_PARPORT_SUNBPP is not set
-# CONFIG_PARPORT_OTHER is not set
-CONFIG_PARPORT_1284=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=m
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_FILTER=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_FWMARK=y
-CONFIG_IP_ROUTE_NAT=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_TOS=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_ROUTE_LARGE_TABLES=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-CONFIG_NET_IPIP=m
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-CONFIG_SYN_COOKIES=y
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-# CONFIG_IP_NF_MATCH_AH_ESP is not set
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_UNCLEAN=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_MIRROR=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-# CONFIG_IP_NF_NAT_LOCAL is not set
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_LOG=m
-# CONFIG_IP_NF_TARGET_ULOG is not set
-CONFIG_IP_NF_TARGET_TCPMSS=m
-# CONFIG_IP_NF_ARPTABLES is not set
-# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-
-#
-# IP: Virtual Server Configuration
-#
-CONFIG_IP_VS=m
-# CONFIG_IP_VS_DEBUG is not set
-CONFIG_IP_VS_TAB_BITS=12
-
-#
-# IPVS scheduler
-#
-CONFIG_IP_VS_RR=m
-CONFIG_IP_VS_WRR=m
-CONFIG_IP_VS_LC=m
-CONFIG_IP_VS_WLC=m
-CONFIG_IP_VS_LBLC=m
-CONFIG_IP_VS_LBLCR=m
-CONFIG_IP_VS_DH=m
-CONFIG_IP_VS_SH=m
-
-#
-# IPVS application helper
-#
-CONFIG_IP_VS_FTP=m
-# CONFIG_IPV6 is not set
-# CONFIG_KHTTPD is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-
-#
-#
-#
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-
-#
-# Appletalk devices
-#
-# CONFIG_DEV_APPLETALK is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Plug and Play configuration
-#
-# CONFIG_PNP is not set
-# CONFIG_ISAPNP is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_CISS_SCSI_TAPE is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_NBD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=65536
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_BLK_STATS is not set
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-# CONFIG_I2O_PCI is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=y
-CONFIG_MD_RAID0=y
-CONFIG_MD_RAID1=y
-CONFIG_MD_RAID5=y
-CONFIG_MD_MULTIPATH=y
-CONFIG_BLK_DEV_LVM=y
-
-#
-# Fusion MPT device support
-#
-CONFIG_FUSION=y
-CONFIG_FUSION_BOOT=y
-CONFIG_FUSION_MAX_SGE=40
-CONFIG_FUSION_ISENSE=m
-CONFIG_FUSION_CTL=m
-CONFIG_FUSION_LAN=m
-CONFIG_NET_FC=y
-
-#
-# ATA/IDE/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
-# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
-# CONFIG_BLK_DEV_IDEDISK_IBM is not set
-# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
-# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
-# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
-# CONFIG_BLK_DEV_IDEDISK_WD is not set
-# CONFIG_BLK_DEV_COMMERIAL is not set
-# CONFIG_BLK_DEV_TIVO is not set
-# CONFIG_BLK_DEV_IDECS is not set
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDETAPE is not set
-CONFIG_BLK_DEV_IDEFLOPPY=y
-CONFIG_BLK_DEV_IDESCSI=y
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-# CONFIG_BLK_DEV_ISAPNP is not set
-# CONFIG_BLK_DEV_RZ1000 is not set
-CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_IDEPCI_SHARE_IRQ=y
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
-# CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_PCI_WIP is not set
-# CONFIG_BLK_DEV_IDEDMA_TIMEOUT is not set
-# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
-CONFIG_BLK_DEV_ADMA=y
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_AEC62XX_TUNING is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_WDC_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-# CONFIG_AMD74XX_OVERRIDE is not set
-CONFIG_BLK_DEV_CMD64X=y
-# CONFIG_BLK_DEV_CMD680 is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_HPT34X_AUTODMA is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_PIIX_TUNING=y
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_PDC202XX is not set
-# CONFIG_PDC202XX_BURST is not set
-# CONFIG_PDC202XX_FORCE is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIS5513 is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX is not set
-# CONFIG_IDE_CHIPSETS is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_DMA_NONPCI is not set
-CONFIG_BLK_DEV_IDE_MODES=y
-# CONFIG_BLK_DEV_ATARAID is not set
-# CONFIG_BLK_DEV_ATARAID_PDC is not set
-# CONFIG_BLK_DEV_ATARAID_HPT is not set
-
-#
-# SCSI support
-#
-CONFIG_SCSI=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_SD_EXTRA_DEVS=40
-CONFIG_CHR_DEV_ST=y
-CONFIG_CHR_DEV_OSST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_SR_EXTRA_DEVS=2
-CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_DEBUG_QUEUES is not set
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AHA1740 is not set
-CONFIG_SCSI_AACRAID=m
-CONFIG_SCSI_AIC7XXX=y
-CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
-CONFIG_AIC7XXX_RESET_DELAY_MS=15000
-# CONFIG_AIC7XXX_PROBE_EISA_VL is not set
-# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_AM53C974 is not set
-CONFIG_SCSI_MEGARAID=y
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_DMA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_PPA is not set
-# CONFIG_SCSI_IMM is not set
-# CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_NCR53C7xx is not set
-CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
-CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
-CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLOGIC_QLA2XXX=y
-CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2100=m
-CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2200=m
-CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2300=m
-# CONFIG_SCSI_SIM710 is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_DEBUG is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-CONFIG_DUMMY=m
-CONFIG_BONDING=m
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_SUNLANCE is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNBMAC is not set
-# CONFIG_SUNQE is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_APRICOT is not set
-# CONFIG_CS89x0 is not set
-# CONFIG_TULIP is not set
-# CONFIG_DE4X5 is not set
-# CONFIG_DGRS is not set
-# CONFIG_DM9102 is not set
-CONFIG_EEPRO100=y
-# CONFIG_E100 is not set
-# CONFIG_LNE390 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_NE3210 is not set
-# CONFIG_ES3210 is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_8139TOO_PIO is not set
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-# CONFIG_8139TOO_8129 is not set
-# CONFIG_8139_OLD_RX_RESET is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_SUNDANCE_MMIO is not set
-# CONFIG_TLAN is not set
-# CONFIG_TC35815 is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_RHINE_MMIO is not set
-# CONFIG_WINBOND_840 is not set
-# CONFIG_NET_POCKET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-CONFIG_ACENIC=m
-CONFIG_ACENIC_OMIT_TIGON_I=y
-# CONFIG_DL2K is not set
-CONFIG_E1000=y
-# CONFIG_MYRI_SBUS is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_SK98LIN is not set
-CONFIG_TIGON3=y
-
-#
-# Quadrics QsNet
-#
-CONFIG_QSNET=m
-CONFIG_ELAN3=m
-CONFIG_EP3=m
-CONFIG_EIP=m
-CONFIG_ELAN4=m
-CONFIG_RMS=m
-CONFIG_JTAG=m
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-CONFIG_NET_FC=y
-CONFIG_IPHASE5526=m
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Input core support
-#
-CONFIG_INPUT=y
-CONFIG_INPUT_KEYBDEV=y
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-CONFIG_INPUT_JOYDEV=m
-CONFIG_INPUT_EVDEV=m
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-CONFIG_SERIAL_HCDP=y
-CONFIG_SERIAL_EXTENDED=y
-CONFIG_SERIAL_ACPI=y
-CONFIG_SERIAL_MANY_PORTS=y
-CONFIG_SERIAL_SHARE_IRQ=y
-# CONFIG_SERIAL_DETECT_IRQ is not set
-CONFIG_SERIAL_MULTIPORT=y
-# CONFIG_HUB6 is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-# CONFIG_PRINTER is not set
-# CONFIG_PPDEV is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=m
-CONFIG_I2C_ALGOBIT=m
-# CONFIG_I2C_PHILIPSPAR is not set
-# CONFIG_I2C_ELV is not set
-# CONFIG_I2C_VELLEMAN is not set
-# CONFIG_I2C_ALGOPCF is not set
-CONFIG_I2C_CHARDEV=m
-CONFIG_I2C_PROC=m
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_MOUSE is not set
-
-#
-# Joysticks
-#
-# CONFIG_INPUT_GAMEPORT is not set
-# CONFIG_INPUT_NS558 is not set
-# CONFIG_INPUT_LIGHTNING is not set
-# CONFIG_INPUT_PCIGAME is not set
-# CONFIG_INPUT_CS461X is not set
-# CONFIG_INPUT_EMU10K1 is not set
-# CONFIG_INPUT_SERIO is not set
-# CONFIG_INPUT_SERPORT is not set
-
-#
-# Joysticks
-#
-# CONFIG_INPUT_ANALOG is not set
-# CONFIG_INPUT_A3D is not set
-# CONFIG_INPUT_ADI is not set
-# CONFIG_INPUT_COBRA is not set
-# CONFIG_INPUT_GF2K is not set
-# CONFIG_INPUT_GRIP is not set
-# CONFIG_INPUT_INTERACT is not set
-# CONFIG_INPUT_TMDC is not set
-# CONFIG_INPUT_SIDEWINDER is not set
-# CONFIG_INPUT_IFORCE_USB is not set
-# CONFIG_INPUT_IFORCE_232 is not set
-# CONFIG_INPUT_WARRIOR is not set
-# CONFIG_INPUT_MAGELLAN is not set
-# CONFIG_INPUT_SPACEORB is not set
-# CONFIG_INPUT_SPACEBALL is not set
-# CONFIG_INPUT_STINGER is not set
-# CONFIG_INPUT_DB9 is not set
-# CONFIG_INPUT_GAMECON is not set
-# CONFIG_INPUT_TURBOGRAFX is not set
-# CONFIG_QIC02_TAPE is not set
-CONFIG_IPMI_HANDLER=m
-CONFIG_IPMI_PANIC_EVENT=y
-CONFIG_IPMI_DEVICE_INTERFACE=m
-CONFIG_IPMI_KCS=m
-CONFIG_IPMI_WATCHDOG=m
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_INTEL_RNG is not set
-# CONFIG_AMD_PM768 is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-CONFIG_EFI_RTC=y
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# File systems
-#
-# CONFIG_QUOTA is not set
-# CONFIG_QFMT_V1 is not set
-# CONFIG_QFMT_V2 is not set
-# CONFIG_QIFACE_COMPAT is not set
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_ADFS_FS is not set
-# CONFIG_ADFS_FS_RW is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BEFS_DEBUG is not set
-# CONFIG_BFS_FS is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-CONFIG_EXT3_FS_XATTR_SHARING=y
-CONFIG_EXT3_FS_XATTR_USER=y
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-# CONFIG_UMSDOS_FS is not set
-CONFIG_VFAT_FS=y
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-CONFIG_CRAMFS=y
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-# CONFIG_ZISOFS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_RW is not set
-# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_XATTR_SHARING=y
-CONFIG_EXT2_FS_XATTR_USER=y
-# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
-# CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
-CONFIG_XFS_FS=y
-# CONFIG_XFS_POSIX_ACL is not set
-CONFIG_XFS_RT=y
-# CONFIG_XFS_QUOTA is not set
-CONFIG_XFS_DMAPI=y
-# CONFIG_XFS_DEBUG is not set
-CONFIG_PAGEBUF_DEBUG=y
-
-#
-# Network File Systems
-#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_TCP is not set
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
-CONFIG_SMB_NLS_REMOTE="cp437"
-# CONFIG_NCP_FS is not set
-# CONFIG_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
-# CONFIG_ZISOFS_FS is not set
-CONFIG_FS_MBCACHE=y
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-CONFIG_EFI_PARTITION=y
-CONFIG_SMB_NLS=y
-CONFIG_NLS=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-# CONFIG_NLS_CODEPAGE_1250 is not set
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=m
-
-#
-# Console drivers
-#
-CONFIG_VGA_CONSOLE=y
-
-#
-# Frame-buffer support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-CONFIG_USB=y
-# CONFIG_USB_DEBUG is not set
-
-#
-# Miscellaneous USB options
-#
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
-# CONFIG_USB_LONG_TIMEOUT is not set
-
-#
-# USB Host Controller Drivers
-#
-# CONFIG_USB_EHCI_HCD is not set
-CONFIG_USB_UHCI_ALT=y
-CONFIG_USB_OHCI=y
-
-#
-# USB Device Class drivers
-#
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_BLUETOOTH is not set
-# CONFIG_USB_MIDI is not set
-# CONFIG_USB_STORAGE is not set
-# CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_DATAFAB is not set
-# CONFIG_USB_STORAGE_FREECOM is not set
-# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_HP8200e is not set
-# CONFIG_USB_STORAGE_SDDR09 is not set
-# CONFIG_USB_STORAGE_SDDR55 is not set
-# CONFIG_USB_STORAGE_JUMPSHOT is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
-
-#
-# USB Human Interface Devices (HID)
-#
-CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT is not set
-# CONFIG_USB_HIDDEV is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_DC2XX is not set
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_SCANNER is not set
-# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
-
-#
-# USB Multimedia devices
-#
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
-# USB Network adaptors
-#
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_CDCETHER is not set
-# CONFIG_USB_USBNET is not set
-
-#
-# USB port drivers
-#
-# CONFIG_USB_USS720 is not set
-
-#
-# USB Serial Converter support
-#
-# CONFIG_USB_SERIAL is not set
-
-#
-# USB Miscellaneous drivers
-#
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_AUERSWALD is not set
-# CONFIG_USB_TIGL is not set
-# CONFIG_USB_BRLVGER is not set
-# CONFIG_USB_LCD is not set
-
-#
-# Library routines
-#
-CONFIG_ZLIB_INFLATE=y
-# CONFIG_ZLIB_DEFLATE is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BLUEZ is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_IA64_GRANULE_16MB is not set
-CONFIG_IA64_GRANULE_64MB=y
-CONFIG_DUMP=m
-CONFIG_DUMP_COMPRESS_RLE=m
-CONFIG_DUMP_COMPRESS_GZIP=m
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_IA64_PRINT_HAZARDS is not set
-# CONFIG_DISABLE_VHPT is not set
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_IA64_EARLY_PRINTK=y
-CONFIG_IA64_EARLY_PRINTK_UART=y
-CONFIG_IA64_EARLY_PRINTK_UART_BASE=0
-# CONFIG_IA64_EARLY_PRINTK_VGA is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_IA64_DEBUG_CMPXCHG is not set
-# CONFIG_IA64_DEBUG_IRQ is not set
-CONFIG_KALLSYMS=y
+++ /dev/null
-#
-# Automatically generated by make menuconfig: don't edit
-#
-CONFIG_X86=y
-# CONFIG_SBUS is not set
-CONFIG_UID16=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Processor type and features
-#
-# CONFIG_LOLAT is not set
-# CONFIG_M386 is not set
-# CONFIG_M486 is not set
-CONFIG_M586=y
-# CONFIG_M586TSC is not set
-# CONFIG_M586MMX is not set
-# CONFIG_M686 is not set
-# CONFIG_MPENTIUMIII is not set
-# CONFIG_MPENTIUM4 is not set
-# CONFIG_MK6 is not set
-# CONFIG_MK7 is not set
-# CONFIG_MELAN is not set
-# CONFIG_MCRUSOE is not set
-# CONFIG_MWINCHIPC6 is not set
-# CONFIG_MWINCHIP2 is not set
-# CONFIG_MWINCHIP3D is not set
-# CONFIG_MCYRIXIII is not set
-CONFIG_X86_WP_WORKS_OK=y
-CONFIG_X86_INVLPG=y
-CONFIG_X86_CMPXCHG=y
-CONFIG_X86_XADD=y
-CONFIG_X86_BSWAP=y
-CONFIG_X86_POPAD_OK=y
-# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_X86_L1_CACHE_SHIFT=5
-CONFIG_X86_USE_STRING_486=y
-CONFIG_X86_ALIGNMENT_16=y
-CONFIG_X86_PPRO_FENCE=y
-# CONFIG_X86_F00F_WORKS_OK is not set
-CONFIG_X86_MCE=y
-
-#
-# CPU Frequency scaling
-#
-# CONFIG_CPU_FREQ is not set
-CONFIG_TOSHIBA=m
-CONFIG_I8K=m
-CONFIG_MICROCODE=m
-CONFIG_X86_MSR=m
-CONFIG_X86_CPUID=m
-# CONFIG_E820_PROC is not set
-CONFIG_EDD=m
-# CONFIG_NOHIGHMEM is not set
-CONFIG_HIGHMEM4G=y
-# CONFIG_HIGHMEM64G is not set
-CONFIG_HIGHMEM=y
-CONFIG_HIGHPTE=y
-CONFIG_HIGHIO=y
-# CONFIG_MATH_EMULATION is not set
-CONFIG_MTRR=y
-CONFIG_SMP=y
-# CONFIG_X86_NUMA is not set
-# CONFIG_X86_TSC_DISABLE is not set
-CONFIG_HAVE_DEC_LOCK=y
-# CONFIG_NOBIGSTACK is not set
-CONFIG_STACK_SIZE_16KB=y
-# CONFIG_STACK_SIZE_32KB is not set
-# CONFIG_STACK_SIZE_64KB is not set
-CONFIG_STACK_SIZE_SHIFT=2
-
-#
-# General setup
-#
-CONFIG_NET=y
-CONFIG_X86_IO_APIC=y
-CONFIG_X86_LOCAL_APIC=y
-CONFIG_PCI=y
-# CONFIG_PCI_GOBIOS is not set
-# CONFIG_PCI_GODIRECT is not set
-CONFIG_PCI_GOANY=y
-CONFIG_PCI_BIOS=y
-CONFIG_PCI_DIRECT=y
-CONFIG_ISA=y
-CONFIG_PCI_NAMES=y
-CONFIG_EISA=y
-# CONFIG_MCA is not set
-CONFIG_HOTPLUG=y
-
-#
-# PCMCIA/CardBus support
-#
-CONFIG_PCMCIA=m
-CONFIG_CARDBUS=y
-CONFIG_TCIC=y
-CONFIG_I82092=y
-CONFIG_I82365=y
-
-#
-# PCI Hotplug Support
-#
-CONFIG_HOTPLUG_PCI=y
-# CONFIG_HOTPLUG_PCI_ACPI is not set
-CONFIG_HOTPLUG_PCI_COMPAQ=m
-# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
-CONFIG_HOTPLUG_PCI_IBM=m
-# CONFIG_HOTPLUG_PCI_H2999 is not set
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=m
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=m
-CONFIG_PM=y
-# CONFIG_ACPI is not set
-CONFIG_APM=y
-# CONFIG_APM_IGNORE_USER_SUSPEND is not set
-# CONFIG_APM_DO_ENABLE is not set
-CONFIG_APM_CPU_IDLE=y
-# CONFIG_APM_DISPLAY_BLANK is not set
-CONFIG_APM_RTC_IS_GMT=y
-# CONFIG_APM_ALLOW_INTS is not set
-# CONFIG_APM_REAL_MODE_POWER_OFF is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-CONFIG_PARPORT=m
-CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_CML1=m
-CONFIG_PARPORT_SERIAL=m
-# CONFIG_PARPORT_PC_FIFO is not set
-# CONFIG_PARPORT_PC_SUPERIO is not set
-CONFIG_PARPORT_PC_PCMCIA=m
-# CONFIG_PARPORT_AMIGA is not set
-# CONFIG_PARPORT_MFC3 is not set
-# CONFIG_PARPORT_ATARI is not set
-# CONFIG_PARPORT_GSC is not set
-# CONFIG_PARPORT_SUNBPP is not set
-# CONFIG_PARPORT_OTHER is not set
-CONFIG_PARPORT_1284=y
-
-#
-# Plug and Play configuration
-#
-CONFIG_PNP=y
-CONFIG_ISAPNP=y
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_FD=y
-CONFIG_BLK_DEV_XD=m
-CONFIG_PARIDE=m
-CONFIG_PARIDE_PARPORT=m
-CONFIG_PARIDE_PD=m
-CONFIG_PARIDE_PCD=m
-CONFIG_PARIDE_PF=m
-CONFIG_PARIDE_PT=m
-CONFIG_PARIDE_PG=m
-CONFIG_PARIDE_ATEN=m
-CONFIG_PARIDE_BPCK=m
-CONFIG_PARIDE_BPCK6=m
-CONFIG_PARIDE_COMM=m
-CONFIG_PARIDE_DSTR=m
-CONFIG_PARIDE_FIT2=m
-CONFIG_PARIDE_FIT3=m
-CONFIG_PARIDE_EPAT=m
-CONFIG_PARIDE_EPATC8=y
-CONFIG_PARIDE_EPIA=m
-CONFIG_PARIDE_FRIQ=m
-CONFIG_PARIDE_FRPW=m
-CONFIG_PARIDE_KBIC=m
-CONFIG_PARIDE_KTTI=m
-CONFIG_PARIDE_ON20=m
-CONFIG_PARIDE_ON26=m
-CONFIG_BLK_CPQ_DA=m
-CONFIG_BLK_CPQ_CISS_DA=m
-CONFIG_CISS_SCSI_TAPE=y
-CONFIG_BLK_DEV_DAC960=m
-CONFIG_BLK_DEV_UMEM=m
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_BLK_STATS=y
-
-#
-# Multi-device support (RAID and LVM)
-#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=m
-CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_RAID5=m
-CONFIG_MD_MULTIPATH=m
-CONFIG_BLK_DEV_LVM=m
-
-#
-# Cryptography support (CryptoAPI)
-#
-CONFIG_CRYPTO=m
-CONFIG_CIPHERS=m
-CONFIG_CIPHER_AES=m
-CONFIG_CIPHER_IDENTITY=m
-CONFIG_CRYPTODEV=m
-CONFIG_CRYPTOLOOP=m
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_FILTER=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_TUX=m
-CONFIG_TUX_EXTCGI=y
-# CONFIG_TUX_EXTENDED_LOG is not set
-# CONFIG_TUX_DEBUG is not set
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_FWMARK=y
-CONFIG_IP_ROUTE_NAT=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_TOS=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_ROUTE_LARGE_TABLES=y
-# CONFIG_IP_PNP is not set
-CONFIG_NET_IPIP=m
-CONFIG_NET_IPGRE=m
-CONFIG_NET_IPGRE_BROADCAST=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-CONFIG_SYN_COOKIES=y
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_UNCLEAN=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_MIRROR=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_NAT_LOCAL=y
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_COMPAT_IPFWADM=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IPV6=m
-
-#
-# IPv6: Netfilter Configuration
-#
-# CONFIG_IP6_NF_QUEUE is not set
-CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_LIMIT=m
-CONFIG_IP6_NF_MATCH_MAC=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
-CONFIG_IP6_NF_MATCH_FRAG=m
-CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
-CONFIG_IP6_NF_MATCH_OWNER=m
-CONFIG_IP6_NF_MATCH_MARK=m
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
-CONFIG_IP6_NF_MATCH_LENGTH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=m
-CONFIG_IP6_NF_TARGET_LOG=m
-CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_MARK=m
-# CONFIG_KHTTPD is not set
-CONFIG_ATM=y
-CONFIG_ATM_CLIP=y
-# CONFIG_ATM_CLIP_NO_ICMP is not set
-CONFIG_ATM_LANE=m
-CONFIG_ATM_MPOA=m
-CONFIG_ATM_BR2684=m
-CONFIG_ATM_BR2684_IPFILTER=y
-CONFIG_VLAN_8021Q=m
-CONFIG_IPX=m
-# CONFIG_IPX_INTERN is not set
-CONFIG_ATALK=m
-
-#
-# Appletalk devices
-#
-CONFIG_DEV_APPLETALK=y
-CONFIG_LTPC=m
-CONFIG_COPS=m
-CONFIG_COPS_DAYNA=y
-CONFIG_COPS_TANGENT=y
-CONFIG_IPDDP=m
-CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
-CONFIG_DECNET=m
-CONFIG_DECNET_SIOCGIFCONF=y
-CONFIG_DECNET_ROUTER=y
-CONFIG_DECNET_ROUTE_FWMARK=y
-CONFIG_BRIDGE=m
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
-CONFIG_NET_DIVERT=y
-# CONFIG_ECONET is not set
-CONFIG_WAN_ROUTER=m
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_CBQ=m
-CONFIG_NET_SCH_HTB=m
-CONFIG_NET_SCH_CSZ=m
-# CONFIG_NET_SCH_ATM is not set
-CONFIG_NET_SCH_PRIO=m
-CONFIG_NET_SCH_RED=m
-CONFIG_NET_SCH_SFQ=m
-CONFIG_NET_SCH_TEQL=m
-CONFIG_NET_SCH_TBF=m
-CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DSMARK=m
-CONFIG_NET_SCH_INGRESS=m
-CONFIG_NET_QOS=y
-CONFIG_NET_ESTIMATOR=y
-CONFIG_NET_CLS=y
-CONFIG_NET_CLS_TCINDEX=m
-CONFIG_NET_CLS_ROUTE4=m
-CONFIG_NET_CLS_ROUTE=y
-CONFIG_NET_CLS_FW=m
-CONFIG_NET_CLS_U32=m
-CONFIG_NET_CLS_RSVP=m
-CONFIG_NET_CLS_RSVP6=m
-CONFIG_NET_CLS_POLICE=y
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-
-#
-# Telephony Support
-#
-CONFIG_PHONE=m
-CONFIG_PHONE_IXJ=m
-CONFIG_PHONE_IXJ_PCMCIA=m
-
-#
-# ATA/IDE/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-# CONFIG_BLK_DEV_HD_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_IDEDISK_MULTI_MODE=y
-# CONFIG_IDEDISK_STROKE is not set
-CONFIG_BLK_DEV_IDECS=m
-CONFIG_BLK_DEV_IDECD=m
-CONFIG_BLK_DEV_IDETAPE=m
-CONFIG_BLK_DEV_IDEFLOPPY=y
-CONFIG_BLK_DEV_IDESCSI=m
-# CONFIG_IDE_TASK_IOCTL is not set
-CONFIG_BLK_DEV_CMD640=y
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-CONFIG_BLK_DEV_ISAPNP=y
-CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_IDEPCI_SHARE_IRQ=y
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
-# CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_PCI_WIP is not set
-CONFIG_BLK_DEV_ADMA100=y
-CONFIG_BLK_DEV_AEC62XX=y
-CONFIG_BLK_DEV_ALI15X3=y
-# CONFIG_WDC_ALI15X3 is not set
-CONFIG_BLK_DEV_AMD74XX=y
-# CONFIG_AMD74XX_OVERRIDE is not set
-CONFIG_BLK_DEV_CMD64X=y
-CONFIG_BLK_DEV_TRIFLEX=y
-CONFIG_BLK_DEV_CY82C693=y
-CONFIG_BLK_DEV_CS5530=y
-CONFIG_BLK_DEV_HPT34X=y
-# CONFIG_HPT34X_AUTODMA is not set
-CONFIG_BLK_DEV_HPT366=y
-CONFIG_BLK_DEV_PIIX=y
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_PDC202XX_OLD=y
-# CONFIG_PDC202XX_BURST is not set
-CONFIG_BLK_DEV_PDC202XX_NEW=y
-CONFIG_PDC202XX_FORCE=y
-CONFIG_BLK_DEV_RZ1000=y
-# CONFIG_BLK_DEV_SC1200 is not set
-CONFIG_BLK_DEV_SVWKS=y
-CONFIG_BLK_DEV_SIIMAGE=y
-CONFIG_BLK_DEV_SIS5513=y
-CONFIG_BLK_DEV_SLC90E66=y
-# CONFIG_BLK_DEV_TRM290 is not set
-CONFIG_BLK_DEV_VIA82CXXX=y
-# CONFIG_IDE_CHIPSETS is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_DMA_NONPCI is not set
-CONFIG_BLK_DEV_PDC202XX=y
-CONFIG_BLK_DEV_IDE_MODES=y
-CONFIG_BLK_DEV_ATARAID=m
-CONFIG_BLK_DEV_ATARAID_PDC=m
-CONFIG_BLK_DEV_ATARAID_HPT=m
-CONFIG_BLK_DEV_ATARAID_SII=m
-
-#
-# SCSI support
-#
-CONFIG_SCSI=m
-CONFIG_BLK_DEV_SD=m
-CONFIG_SD_EXTRA_DEVS=40
-CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
-CONFIG_BLK_DEV_SR=m
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_SR_EXTRA_DEVS=4
-CONFIG_CHR_DEV_SG=m
-# CONFIG_SCSI_DEBUG_QUEUES is not set
-# CONFIG_SCSI_MULTI_LUN is not set
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-
-#
-# SCSI low-level drivers
-#
-CONFIG_BLK_DEV_3W_XXXX_RAID=m
-CONFIG_SCSI_7000FASST=m
-CONFIG_SCSI_ACARD=m
-CONFIG_SCSI_AHA152X=m
-CONFIG_SCSI_AHA1542=m
-CONFIG_SCSI_AHA1740=m
-CONFIG_SCSI_AACRAID=m
-CONFIG_SCSI_AIC7XXX=m
-CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
-CONFIG_AIC7XXX_RESET_DELAY_MS=15000
-# CONFIG_AIC7XXX_PROBE_EISA_VL is not set
-# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
-CONFIG_SCSI_AIC79XX=m
-CONFIG_AIC79XX_CMDS_PER_DEVICE=253
-CONFIG_AIC79XX_RESET_DELAY_MS=15000
-# CONFIG_AIC79XX_BUILD_FIRMWARE is not set
-CONFIG_AIC79XX_ENABLE_RD_STRM=y
-# CONFIG_AIC79XX_DEBUG_ENABLE is not set
-CONFIG_AIC79XX_DEBUG_MASK=0
-CONFIG_SCSI_AIC7XXX_OLD=m
-CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y
-CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=32
-CONFIG_AIC7XXX_OLD_PROC_STATS=y
-CONFIG_SCSI_DPT_I2O=m
-CONFIG_SCSI_ADVANSYS=m
-CONFIG_SCSI_IN2000=m
-CONFIG_SCSI_AM53C974=m
-CONFIG_SCSI_MEGARAID=m
-CONFIG_SCSI_BUSLOGIC=m
-# CONFIG_SCSI_OMIT_FLASHPOINT is not set
-CONFIG_SCSI_CPQFCTS=m
-CONFIG_SCSI_DMX3191D=m
-CONFIG_SCSI_DTC3280=m
-CONFIG_SCSI_EATA=m
-CONFIG_SCSI_EATA_TAGGED_QUEUE=y
-# CONFIG_SCSI_EATA_LINKED_COMMANDS is not set
-CONFIG_SCSI_EATA_MAX_TAGS=16
-CONFIG_SCSI_EATA_DMA=m
-CONFIG_SCSI_EATA_PIO=m
-CONFIG_SCSI_FUTURE_DOMAIN=m
-CONFIG_SCSI_GDTH=m
-CONFIG_SCSI_GENERIC_NCR5380=m
-# CONFIG_SCSI_GENERIC_NCR53C400 is not set
-CONFIG_SCSI_G_NCR5380_PORT=y
-# CONFIG_SCSI_G_NCR5380_MEM is not set
-CONFIG_SCSI_IPS=m
-CONFIG_SCSI_INITIO=m
-CONFIG_SCSI_INIA100=m
-CONFIG_SCSI_PPA=m
-CONFIG_SCSI_IMM=m
-# CONFIG_SCSI_IZIP_EPP16 is not set
-# CONFIG_SCSI_IZIP_SLOW_CTR is not set
-CONFIG_SCSI_NCR53C406A=m
-CONFIG_SCSI_NCR53C7xx=m
-# CONFIG_SCSI_NCR53C7xx_sync is not set
-CONFIG_SCSI_NCR53C7xx_FAST=y
-CONFIG_SCSI_NCR53C7xx_DISCONNECT=y
-CONFIG_SCSI_SYM53C8XX_2=m
-CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
-CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
-CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
-CONFIG_SCSI_NCR53C8XX=m
-CONFIG_SCSI_SYM53C8XX=m
-CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
-CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
-CONFIG_SCSI_NCR53C8XX_SYNC=40
-# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
-# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set
-# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
-CONFIG_SCSI_PAS16=m
-CONFIG_SCSI_PCI2000=m
-CONFIG_SCSI_PCI2220I=m
-CONFIG_SCSI_PSI240I=m
-CONFIG_SCSI_QLOGIC_FAS=m
-CONFIG_SCSI_QLOGIC_ISP=m
-CONFIG_SCSI_QLOGIC_FC=m
-# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
-CONFIG_SCSI_QLOGIC_1280=m
-CONFIG_SCSI_NEWISP=m
-CONFIG_SCSI_SEAGATE=m
-CONFIG_SCSI_SIM710=m
-CONFIG_SCSI_SYM53C416=m
-CONFIG_SCSI_DC390T=m
-# CONFIG_SCSI_DC390T_NOGENSUPP is not set
-CONFIG_SCSI_T128=m
-CONFIG_SCSI_U14_34F=m
-# CONFIG_SCSI_U14_34F_LINKED_COMMANDS is not set
-CONFIG_SCSI_U14_34F_MAX_TAGS=8
-CONFIG_SCSI_ULTRASTOR=m
-CONFIG_SCSI_NSP32=m
-CONFIG_SCSI_DEBUG=m
-
-#
-# PCMCIA SCSI adapter support
-#
-CONFIG_SCSI_PCMCIA=y
-CONFIG_PCMCIA_AHA152X=m
-CONFIG_PCMCIA_FDOMAIN=m
-CONFIG_PCMCIA_NINJA_SCSI=m
-CONFIG_PCMCIA_QLOGIC=m
-
-#
-# Fusion MPT device support
-#
-CONFIG_FUSION=m
-# CONFIG_FUSION_BOOT is not set
-CONFIG_FUSION_MAX_SGE=40
-# CONFIG_FUSION_ISENSE is not set
-CONFIG_FUSION_CTL=m
-CONFIG_FUSION_LAN=m
-CONFIG_NET_FC=y
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-CONFIG_IEEE1394=m
-# CONFIG_IEEE1394_PCILYNX is not set
-CONFIG_IEEE1394_OHCI1394=m
-CONFIG_IEEE1394_VIDEO1394=m
-CONFIG_IEEE1394_SBP2=m
-CONFIG_IEEE1394_SBP2_PHYS_DMA=y
-CONFIG_IEEE1394_ETH1394=m
-CONFIG_IEEE1394_DV1394=m
-CONFIG_IEEE1394_RAWIO=m
-CONFIG_IEEE1394_CMP=m
-CONFIG_IEEE1394_AMDTP=m
-# CONFIG_IEEE1394_VERBOSEDEBUG is not set
-
-#
-# I2O device support
-#
-CONFIG_I2O=m
-CONFIG_I2O_PCI=m
-CONFIG_I2O_BLOCK=m
-CONFIG_I2O_LAN=m
-CONFIG_I2O_SCSI=m
-CONFIG_I2O_PROC=m
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-CONFIG_DUMMY=m
-CONFIG_BONDING=m
-CONFIG_EQUALIZER=m
-CONFIG_TUN=m
-CONFIG_ETHERTAP=m
-CONFIG_NET_SB1000=m
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_SUNLANCE is not set
-CONFIG_HAPPYMEAL=m
-# CONFIG_SUNBMAC is not set
-# CONFIG_SUNQE is not set
-CONFIG_SUNGEM=m
-CONFIG_NET_VENDOR_3COM=y
-CONFIG_EL1=m
-CONFIG_EL2=m
-CONFIG_ELPLUS=m
-CONFIG_EL16=m
-CONFIG_EL3=m
-CONFIG_3C515=m
-# CONFIG_ELMC is not set
-# CONFIG_ELMC_II is not set
-CONFIG_VORTEX=m
-CONFIG_TYPHOON=m
-CONFIG_LANCE=m
-CONFIG_NET_VENDOR_SMC=y
-CONFIG_WD80x3=m
-# CONFIG_ULTRAMCA is not set
-CONFIG_ULTRA=m
-CONFIG_ULTRA32=m
-CONFIG_SMC9194=m
-CONFIG_NET_VENDOR_RACAL=y
-CONFIG_NI5010=m
-CONFIG_NI52=m
-CONFIG_NI65=m
-CONFIG_AT1700=m
-CONFIG_DEPCA=m
-CONFIG_HP100=m
-CONFIG_NET_ISA=y
-CONFIG_E2100=m
-# CONFIG_EWRK3 is not set
-CONFIG_EEXPRESS=m
-CONFIG_EEXPRESS_PRO=m
-CONFIG_HPLAN_PLUS=m
-CONFIG_HPLAN=m
-CONFIG_LP486E=m
-CONFIG_ETH16I=m
-CONFIG_NE2000=m
-CONFIG_NET_PCI=y
-CONFIG_PCNET32=m
-CONFIG_AMD8111_ETH=m
-CONFIG_ADAPTEC_STARFIRE=m
-CONFIG_AC3200=m
-CONFIG_APRICOT=m
-CONFIG_CS89x0=m
-CONFIG_TULIP=m
-# CONFIG_TULIP_MWI is not set
-CONFIG_TULIP_MMIO=y
-CONFIG_DE4X5=m
-CONFIG_DGRS=m
-CONFIG_DM9102=m
-CONFIG_EEPRO100=m
-# CONFIG_EEPRO100_PIO is not set
-CONFIG_E100=m
-CONFIG_LNE390=m
-CONFIG_FEALNX=m
-CONFIG_NATSEMI=m
-CONFIG_NE2K_PCI=m
-CONFIG_NE3210=m
-CONFIG_ES3210=m
-CONFIG_8139CP=m
-CONFIG_8139TOO=m
-# CONFIG_8139TOO_PIO is not set
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-CONFIG_8139TOO_8129=y
-# CONFIG_8139_OLD_RX_RESET is not set
-CONFIG_SIS900=m
-CONFIG_EPIC100=m
-CONFIG_SUNDANCE=m
-# CONFIG_SUNDANCE_MMIO is not set
-CONFIG_TLAN=m
-CONFIG_TC35815=m
-CONFIG_VIA_RHINE=m
-# CONFIG_VIA_RHINE_MMIO is not set
-CONFIG_WINBOND_840=m
-CONFIG_NET_POCKET=y
-CONFIG_ATP=m
-CONFIG_DE600=m
-CONFIG_DE620=m
-
-#
-# Ethernet (1000 Mbit)
-#
-CONFIG_ACENIC=m
-# CONFIG_ACENIC_OMIT_TIGON_I is not set
-CONFIG_DL2K=m
-CONFIG_E1000=m
-# CONFIG_MYRI_SBUS is not set
-CONFIG_NS83820=m
-CONFIG_HAMACHI=m
-CONFIG_YELLOWFIN=m
-CONFIG_R8169=m
-CONFIG_SK98LIN=m
-CONFIG_TIGON3=m
-CONFIG_FDDI=y
-CONFIG_DEFXX=m
-CONFIG_SKFP=m
-CONFIG_NETCONSOLE=m
-# CONFIG_HIPPI is not set
-CONFIG_PLIP=m
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-# CONFIG_PPP_BSDCOMP is not set
-CONFIG_PPPOE=m
-CONFIG_PPPOATM=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-CONFIG_SLIP_MODE_SLIP6=y
-
-#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-CONFIG_STRIP=m
-CONFIG_WAVELAN=m
-CONFIG_ARLAN=m
-CONFIG_AIRONET4500=m
-CONFIG_AIRONET4500_NONCS=m
-CONFIG_AIRONET4500_PNP=y
-CONFIG_AIRONET4500_PCI=y
-CONFIG_AIRONET4500_ISA=y
-CONFIG_AIRONET4500_I365=y
-CONFIG_AIRONET4500_PROC=m
-CONFIG_AIRO=m
-CONFIG_HERMES=m
-CONFIG_PLX_HERMES=m
-CONFIG_PCI_HERMES=m
-CONFIG_PCMCIA_HERMES=m
-CONFIG_AIRO_CS=m
-CONFIG_NET_WIRELESS=y
-CONFIG_PCMCIA_HERMES_OLD=m
-
-#
-# Token Ring devices
-#
-CONFIG_TR=y
-CONFIG_IBMTR=m
-CONFIG_IBMOL=m
-CONFIG_IBMLS=m
-CONFIG_3C359=m
-CONFIG_TMS380TR=m
-CONFIG_TMSPCI=m
-CONFIG_TMSISA=m
-CONFIG_ABYSS=m
-# CONFIG_MADGEMC is not set
-CONFIG_SMCTR=m
-CONFIG_NET_FC=y
-CONFIG_IPHASE5526=m
-CONFIG_RCPCI=m
-CONFIG_SHAPER=m
-
-#
-# Wan interfaces
-#
-CONFIG_WAN=y
-CONFIG_HOSTESS_SV11=m
-CONFIG_COSA=m
-# CONFIG_COMX is not set
-# CONFIG_DSCC4 is not set
-# CONFIG_LANMEDIA is not set
-CONFIG_ATI_XX20=m
-CONFIG_SEALEVEL_4021=m
-# CONFIG_SYNCLINK_SYNCPPP is not set
-# CONFIG_HDLC is not set
-CONFIG_DLCI=m
-CONFIG_DLCI_COUNT=24
-CONFIG_DLCI_MAX=8
-CONFIG_SDLA=m
-CONFIG_WAN_ROUTER_DRIVERS=y
-CONFIG_VENDOR_SANGOMA=m
-CONFIG_WANPIPE_CHDLC=y
-CONFIG_WANPIPE_FR=y
-CONFIG_WANPIPE_X25=y
-CONFIG_WANPIPE_PPP=y
-CONFIG_WANPIPE_MULTPPP=y
-CONFIG_CYCLADES_SYNC=m
-CONFIG_CYCLOMX_X25=y
-# CONFIG_LAPBETHER is not set
-# CONFIG_X25_ASY is not set
-CONFIG_SBNI=m
-CONFIG_SBNI_MULTILINE=y
-
-#
-# PCMCIA network device support
-#
-CONFIG_NET_PCMCIA=y
-CONFIG_PCMCIA_3C589=m
-CONFIG_PCMCIA_3C574=m
-CONFIG_PCMCIA_FMVJ18X=m
-CONFIG_PCMCIA_PCNET=m
-CONFIG_PCMCIA_AXNET=m
-CONFIG_PCMCIA_NMCLAN=m
-CONFIG_PCMCIA_SMC91C92=m
-CONFIG_PCMCIA_XIRC2PS=m
-# CONFIG_ARCNET_COM20020_CS is not set
-CONFIG_PCMCIA_IBMTR=m
-CONFIG_PCMCIA_XIRCOM=m
-CONFIG_PCMCIA_XIRTULIP=m
-CONFIG_NET_PCMCIA_RADIO=y
-CONFIG_PCMCIA_RAYCS=m
-CONFIG_PCMCIA_NETWAVE=m
-CONFIG_PCMCIA_WAVELAN=m
-CONFIG_PCMCIA_WVLAN=m
-CONFIG_AIRONET4500_CS=m
-
-#
-# ATM drivers
-#
-CONFIG_ATM_TCP=m
-CONFIG_ATM_LANAI=m
-CONFIG_ATM_ENI=m
-# CONFIG_ATM_ENI_DEBUG is not set
-# CONFIG_ATM_ENI_TUNE_BURST is not set
-CONFIG_ATM_FIRESTREAM=m
-CONFIG_ATM_ZATM=m
-# CONFIG_ATM_ZATM_DEBUG is not set
-CONFIG_ATM_ZATM_EXACT_TS=y
-CONFIG_ATM_NICSTAR=m
-CONFIG_ATM_NICSTAR_USE_SUNI=y
-CONFIG_ATM_NICSTAR_USE_IDT77105=y
-CONFIG_ATM_IDT77252=m
-# CONFIG_ATM_IDT77252_DEBUG is not set
-# CONFIG_ATM_IDT77252_RCV_ALL is not set
-CONFIG_ATM_IDT77252_USE_SUNI=y
-CONFIG_ATM_AMBASSADOR=m
-# CONFIG_ATM_AMBASSADOR_DEBUG is not set
-CONFIG_ATM_HORIZON=m
-# CONFIG_ATM_HORIZON_DEBUG is not set
-CONFIG_ATM_IA=m
-# CONFIG_ATM_IA_DEBUG is not set
-CONFIG_ATM_FORE200E_MAYBE=m
-CONFIG_ATM_FORE200E_PCA=y
-CONFIG_ATM_FORE200E_PCA_DEFAULT_FW=y
-CONFIG_ATM_FORE200E_TX_RETRY=16
-CONFIG_ATM_FORE200E_DEBUG=0
-CONFIG_ATM_FORE200E=m
-
-#
-# Amateur Radio support
-#
-CONFIG_HAMRADIO=y
-CONFIG_AX25=m
-# CONFIG_AX25_DAMA_SLAVE is not set
-CONFIG_NETROM=m
-CONFIG_ROSE=m
-
-#
-# AX.25 network device drivers
-#
-# CONFIG_MKISS is not set
-# CONFIG_6PACK is not set
-# CONFIG_BPQETHER is not set
-# CONFIG_DMASCC is not set
-# CONFIG_SCC is not set
-# CONFIG_BAYCOM_SER_FDX is not set
-# CONFIG_BAYCOM_SER_HDX is not set
-# CONFIG_BAYCOM_PAR is not set
-# CONFIG_BAYCOM_EPP is not set
-CONFIG_SOUNDMODEM=m
-CONFIG_SOUNDMODEM_SBC=y
-CONFIG_SOUNDMODEM_WSS=y
-CONFIG_SOUNDMODEM_AFSK1200=y
-CONFIG_SOUNDMODEM_AFSK2400_7=y
-CONFIG_SOUNDMODEM_AFSK2400_8=y
-CONFIG_SOUNDMODEM_AFSK2666=y
-CONFIG_SOUNDMODEM_HAPN4800=y
-CONFIG_SOUNDMODEM_PSK4800=y
-CONFIG_SOUNDMODEM_FSK9600=y
-# CONFIG_YAM is not set
-
-#
-# IrDA (infrared) support
-#
-CONFIG_IRDA=m
-CONFIG_IRLAN=m
-CONFIG_IRNET=m
-CONFIG_IRCOMM=m
-CONFIG_IRDA_ULTRA=y
-CONFIG_IRDA_CACHE_LAST_LSAP=y
-CONFIG_IRDA_FAST_RR=y
-# CONFIG_IRDA_DEBUG is not set
-
-#
-# Infrared-port device drivers
-#
-CONFIG_IRTTY_SIR=m
-CONFIG_IRPORT_SIR=m
-CONFIG_DONGLE=y
-CONFIG_ESI_DONGLE=m
-CONFIG_ACTISYS_DONGLE=m
-CONFIG_TEKRAM_DONGLE=m
-CONFIG_GIRBIL_DONGLE=m
-CONFIG_LITELINK_DONGLE=m
-CONFIG_MCP2120_DONGLE=m
-CONFIG_OLD_BELKIN_DONGLE=m
-CONFIG_ACT200L_DONGLE=m
-CONFIG_MA600_DONGLE=m
-CONFIG_USB_IRDA=m
-CONFIG_NSC_FIR=m
-CONFIG_WINBOND_FIR=m
-CONFIG_TOSHIBA_OLD=m
-CONFIG_TOSHIBA_FIR=m
-CONFIG_SMC_IRCC_FIR=m
-CONFIG_ALI_FIR=m
-CONFIG_VLSI_FIR=m
-
-#
-# ISDN subsystem
-#
-CONFIG_ISDN=m
-CONFIG_ISDN_BOOL=y
-CONFIG_ISDN_PPP=y
-CONFIG_ISDN_PPP_VJ=y
-CONFIG_ISDN_MPP=y
-CONFIG_ISDN_PPP_BSDCOMP=m
-CONFIG_ISDN_AUDIO=y
-CONFIG_ISDN_TTY_FAX=y
-
-#
-# ISDN feature submodules
-#
-CONFIG_ISDN_DRV_LOOP=m
-# CONFIG_ISDN_DIVERSION is not set
-
-#
-# Passive ISDN cards
-#
-CONFIG_ISDN_DRV_HISAX=m
-CONFIG_ISDN_HISAX=y
-CONFIG_HISAX_EURO=y
-CONFIG_DE_AOC=y
-# CONFIG_HISAX_NO_SENDCOMPLETE is not set
-# CONFIG_HISAX_NO_LLC is not set
-# CONFIG_HISAX_NO_KEYPAD is not set
-CONFIG_HISAX_1TR6=y
-CONFIG_HISAX_NI1=y
-CONFIG_HISAX_MAX_CARDS=8
-CONFIG_HISAX_16_0=y
-CONFIG_HISAX_16_3=y
-CONFIG_HISAX_AVM_A1=y
-CONFIG_HISAX_IX1MICROR2=y
-CONFIG_HISAX_ASUSCOM=y
-CONFIG_HISAX_TELEINT=y
-CONFIG_HISAX_HFCS=y
-CONFIG_HISAX_SPORTSTER=y
-CONFIG_HISAX_MIC=y
-CONFIG_HISAX_ISURF=y
-CONFIG_HISAX_HSTSAPHIR=y
-CONFIG_HISAX_TELESPCI=y
-CONFIG_HISAX_S0BOX=y
-CONFIG_HISAX_FRITZPCI=y
-CONFIG_HISAX_AVM_A1_PCMCIA=y
-CONFIG_HISAX_ELSA=y
-CONFIG_HISAX_DIEHLDIVA=y
-CONFIG_HISAX_SEDLBAUER=y
-CONFIG_HISAX_NETJET=y
-CONFIG_HISAX_NETJET_U=y
-CONFIG_HISAX_NICCY=y
-CONFIG_HISAX_BKM_A4T=y
-CONFIG_HISAX_SCT_QUADRO=y
-CONFIG_HISAX_GAZEL=y
-CONFIG_HISAX_HFC_PCI=y
-CONFIG_HISAX_W6692=y
-CONFIG_HISAX_HFC_SX=y
-CONFIG_HISAX_ENTERNOW_PCI=y
-CONFIG_HISAX_DEBUG=y
-CONFIG_HISAX_SEDLBAUER_CS=m
-CONFIG_HISAX_ELSA_CS=m
-CONFIG_HISAX_AVM_A1_CS=m
-CONFIG_HISAX_ST5481=m
-CONFIG_HISAX_FRITZ_PCIPNP=m
-CONFIG_USB_AUERISDN=m
-
-#
-# Active ISDN cards
-#
-CONFIG_ISDN_DRV_ICN=m
-CONFIG_ISDN_DRV_PCBIT=m
-# CONFIG_ISDN_DRV_SC is not set
-# CONFIG_ISDN_DRV_ACT2000 is not set
-CONFIG_ISDN_DRV_EICON=y
-CONFIG_ISDN_DRV_EICON_DIVAS=m
-# CONFIG_ISDN_DRV_EICON_OLD is not set
-CONFIG_ISDN_DRV_TPAM=m
-CONFIG_ISDN_CAPI=m
-CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
-CONFIG_ISDN_CAPI_MIDDLEWARE=y
-CONFIG_ISDN_CAPI_CAPI20=m
-CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
-CONFIG_ISDN_CAPI_CAPIFS=m
-CONFIG_ISDN_CAPI_CAPIDRV=m
-CONFIG_ISDN_DRV_AVMB1_B1ISA=m
-CONFIG_ISDN_DRV_AVMB1_B1PCI=m
-CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
-CONFIG_ISDN_DRV_AVMB1_T1ISA=m
-CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
-CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
-CONFIG_ISDN_DRV_AVMB1_T1PCI=m
-CONFIG_ISDN_DRV_AVMB1_C4=m
-CONFIG_HYSDN=m
-CONFIG_HYSDN_CAPI=y
-CONFIG_KALLSYMS=y
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Input core support
-#
-CONFIG_INPUT=m
-CONFIG_INPUT_KEYBDEV=m
-CONFIG_INPUT_MOUSEDEV=m
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-CONFIG_INPUT_JOYDEV=m
-CONFIG_INPUT_EVDEV=m
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_ECC=m
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-CONFIG_SERIAL_EXTENDED=y
-CONFIG_SERIAL_MANY_PORTS=y
-CONFIG_SERIAL_SHARE_IRQ=y
-# CONFIG_SERIAL_DETECT_IRQ is not set
-CONFIG_SERIAL_MULTIPORT=y
-# CONFIG_HUB6 is not set
-CONFIG_SERIAL_NONSTANDARD=y
-CONFIG_COMPUTONE=m
-CONFIG_ROCKETPORT=m
-CONFIG_CYCLADES=m
-# CONFIG_CYZ_INTR is not set
-CONFIG_DIGIEPCA=m
-CONFIG_ESPSERIAL=m
-CONFIG_MOXA_INTELLIO=m
-CONFIG_MOXA_SMARTIO=m
-CONFIG_ISI=m
-CONFIG_SYNCLINK=m
-# CONFIG_SYNCLINKMP is not set
-CONFIG_N_HDLC=m
-CONFIG_RISCOM8=m
-CONFIG_SPECIALIX=m
-CONFIG_SPECIALIX_RTSCTS=y
-CONFIG_SX=m
-# CONFIG_RIO is not set
-CONFIG_STALDRV=y
-CONFIG_STALLION=m
-CONFIG_ISTALLION=m
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=2048
-CONFIG_PRINTER=m
-CONFIG_LP_CONSOLE=y
-CONFIG_PPDEV=m
-CONFIG_TIPAR=m
-
-#
-# I2C support
-#
-CONFIG_I2C=m
-CONFIG_I2C_ALGOBIT=m
-CONFIG_I2C_PHILIPSPAR=m
-CONFIG_I2C_ELV=m
-CONFIG_I2C_VELLEMAN=m
-# CONFIG_SCx200_I2C is not set
-# CONFIG_SCx200_ACB is not set
-CONFIG_I2C_ALGOPCF=m
-CONFIG_I2C_ELEKTOR=m
-CONFIG_I2C_MAINBOARD=y
-CONFIG_I2C_ALI1535=m
-CONFIG_I2C_ALI15X3=m
-CONFIG_I2C_HYDRA=m
-CONFIG_I2C_AMD756=m
-# CONFIG_I2C_TSUNAMI is not set
-CONFIG_I2C_I801=m
-# CONFIG_I2C_I810 is not set
-CONFIG_I2C_PIIX4=m
-CONFIG_I2C_SIS5595=m
-CONFIG_I2C_VIA=m
-CONFIG_I2C_VIAPRO=m
-CONFIG_I2C_VOODOO3=m
-CONFIG_I2C_ISA=m
-CONFIG_I2C_CHARDEV=m
-CONFIG_I2C_PROC=m
-
-#
-# Hardware sensors support
-#
-CONFIG_SENSORS=y
-CONFIG_SENSORS_ADM1021=m
-CONFIG_SENSORS_ADM1024=m
-CONFIG_SENSORS_ADM1025=m
-CONFIG_SENSORS_ADM9240=m
-CONFIG_SENSORS_DS1621=m
-CONFIG_SENSORS_FSCPOS=m
-CONFIG_SENSORS_FSCSCY=m
-CONFIG_SENSORS_GL518SM=m
-CONFIG_SENSORS_GL520SM=m
-CONFIG_SENSORS_MAXILIFE=m
-CONFIG_SENSORS_IT87=m
-CONFIG_SENSORS_MTP008=m
-CONFIG_SENSORS_LM75=m
-CONFIG_SENSORS_LM78=m
-CONFIG_SENSORS_LM80=m
-CONFIG_SENSORS_LM87=m
-CONFIG_SENSORS_LM92=m
-CONFIG_SENSORS_SIS5595=m
-CONFIG_SENSORS_SMSC47M1=m
-CONFIG_SENSORS_THMC50=m
-CONFIG_SENSORS_VIA686A=m
-CONFIG_SENSORS_VT1211=m
-CONFIG_SENSORS_VT8231=m
-CONFIG_SENSORS_W83781D=m
-CONFIG_SENSORS_OTHER=y
-CONFIG_SENSORS_BT869=m
-CONFIG_SENSORS_DDCMON=m
-CONFIG_SENSORS_EEPROM=m
-CONFIG_SENSORS_MATORB=m
-CONFIG_SENSORS_PCF8574=m
-CONFIG_SENSORS_PCF8591=m
-
-#
-# Mice
-#
-CONFIG_BUSMOUSE=m
-CONFIG_ATIXL_BUSMOUSE=m
-CONFIG_LOGIBUSMOUSE=m
-CONFIG_MS_BUSMOUSE=m
-CONFIG_MOUSE=y
-CONFIG_PSMOUSE=y
-CONFIG_82C710_MOUSE=m
-CONFIG_PC110_PAD=m
-CONFIG_MK712_MOUSE=m
-
-#
-# Joysticks
-#
-CONFIG_INPUT_GAMEPORT=m
-CONFIG_INPUT_NS558=m
-CONFIG_INPUT_LIGHTNING=m
-CONFIG_INPUT_PCIGAME=m
-CONFIG_INPUT_CS461X=m
-CONFIG_INPUT_EMU10K1=m
-CONFIG_INPUT_SERIO=m
-CONFIG_INPUT_SERPORT=m
-CONFIG_INPUT_ANALOG=m
-CONFIG_INPUT_A3D=m
-CONFIG_INPUT_ADI=m
-CONFIG_INPUT_COBRA=m
-CONFIG_INPUT_GF2K=m
-CONFIG_INPUT_GRIP=m
-CONFIG_INPUT_INTERACT=m
-CONFIG_INPUT_TMDC=m
-CONFIG_INPUT_SIDEWINDER=m
-CONFIG_INPUT_IFORCE_USB=m
-CONFIG_INPUT_IFORCE_232=m
-CONFIG_INPUT_WARRIOR=m
-CONFIG_INPUT_MAGELLAN=m
-CONFIG_INPUT_SPACEORB=m
-CONFIG_INPUT_SPACEBALL=m
-CONFIG_INPUT_STINGER=m
-CONFIG_INPUT_DB9=m
-CONFIG_INPUT_GAMECON=m
-CONFIG_INPUT_TURBOGRAFX=m
-# CONFIG_QIC02_TAPE is not set
-CONFIG_IPMI_HANDLER=m
-# CONFIG_IPMI_PANIC_EVENT is not set
-CONFIG_IPMI_DEVICE_INTERFACE=m
-CONFIG_IPMI_KCS=m
-CONFIG_IPMI_WATCHDOG=m
-
-#
-# Watchdog Cards
-#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-CONFIG_ACQUIRE_WDT=m
-CONFIG_ADVANTECH_WDT=m
-CONFIG_ALIM7101_WDT=m
-CONFIG_SC520_WDT=m
-CONFIG_PCWATCHDOG=m
-CONFIG_EUROTECH_WDT=m
-CONFIG_IB700_WDT=m
-CONFIG_WAFER_WDT=m
-CONFIG_I810_TCO=m
-# CONFIG_MIXCOMWD is not set
-# CONFIG_60XX_WDT is not set
-CONFIG_SC1200_WDT=m
-# CONFIG_SCx200_WDT is not set
-CONFIG_SOFT_WATCHDOG=m
-CONFIG_W83877F_WDT=m
-CONFIG_WDT=m
-CONFIG_WDTPCI=m
-# CONFIG_WDT_501 is not set
-CONFIG_MACHZ_WDT=m
-CONFIG_AMD7XX_TCO=m
-# CONFIG_SCx200_GPIO is not set
-CONFIG_AMD_RNG=m
-CONFIG_INTEL_RNG=m
-CONFIG_AMD_PM768=m
-CONFIG_NVRAM=m
-CONFIG_RTC=y
-CONFIG_DTLK=m
-CONFIG_R3964=m
-# CONFIG_APPLICOM is not set
-CONFIG_SONYPI=m
-
-#
-# Ftape, the floppy tape device driver
-#
-CONFIG_FTAPE=m
-CONFIG_ZFTAPE=m
-CONFIG_ZFT_DFLT_BLK_SZ=10240
-CONFIG_ZFT_COMPRESSOR=m
-CONFIG_FT_NR_BUFFERS=3
-# CONFIG_FT_PROC_FS is not set
-CONFIG_FT_NORMAL_DEBUG=y
-# CONFIG_FT_FULL_DEBUG is not set
-# CONFIG_FT_NO_TRACE is not set
-# CONFIG_FT_NO_TRACE_AT_ALL is not set
-CONFIG_FT_STD_FDC=y
-# CONFIG_FT_MACH2 is not set
-# CONFIG_FT_PROBE_FC10 is not set
-# CONFIG_FT_ALT_FDC is not set
-CONFIG_FT_FDC_THR=8
-CONFIG_FT_FDC_MAX_RATE=2000
-CONFIG_FT_ALPHA_CLOCK=0
-CONFIG_AGP=m
-CONFIG_AGP_INTEL=y
-CONFIG_AGP_I810=y
-CONFIG_AGP_VIA=y
-CONFIG_AGP_AMD=y
-CONFIG_AGP_AMD_8151=y
-CONFIG_AGP_SIS=y
-CONFIG_AGP_ALI=y
-CONFIG_AGP_SWORKS=y
-CONFIG_DRM=y
-# CONFIG_DRM_OLD is not set
-CONFIG_DRM_NEW=y
-CONFIG_DRM_TDFX=m
-CONFIG_DRM_R128=m
-CONFIG_DRM_RADEON=m
-CONFIG_DRM_I810=m
-# CONFIG_DRM_I810_XFREE_41 is not set
-CONFIG_DRM_I830=m
-CONFIG_DRM_MGA=m
-# CONFIG_DRM_SIS is not set
-
-#
-# PCMCIA character devices
-#
-CONFIG_PCMCIA_SERIAL_CS=m
-CONFIG_SYNCLINK_CS=m
-CONFIG_MWAVE=m
-CONFIG_BATTERY_GERICOM=m
-
-#
-# Multimedia devices
-#
-CONFIG_VIDEO_DEV=m
-
-#
-# Video For Linux
-#
-CONFIG_VIDEO_PROC_FS=y
-CONFIG_I2C_PARPORT=m
-CONFIG_VIDEO_BT848=m
-CONFIG_VIDEO_PMS=m
-CONFIG_VIDEO_BWQCAM=m
-CONFIG_VIDEO_CQCAM=m
-CONFIG_VIDEO_W9966=m
-CONFIG_VIDEO_CPIA=m
-CONFIG_VIDEO_CPIA_PP=m
-CONFIG_VIDEO_CPIA_USB=m
-CONFIG_VIDEO_SAA5249=m
-CONFIG_TUNER_3036=m
-CONFIG_VIDEO_STRADIS=m
-CONFIG_VIDEO_ZORAN=m
-CONFIG_VIDEO_ZORAN_BUZ=m
-CONFIG_VIDEO_ZORAN_DC10=m
-CONFIG_VIDEO_ZORAN_LML33=m
-CONFIG_VIDEO_ZR36120=m
-CONFIG_VIDEO_MEYE=m
-
-#
-# Radio Adapters
-#
-CONFIG_RADIO_CADET=m
-CONFIG_RADIO_RTRACK=m
-CONFIG_RADIO_RTRACK2=m
-CONFIG_RADIO_AZTECH=m
-CONFIG_RADIO_GEMTEK=m
-CONFIG_RADIO_GEMTEK_PCI=m
-CONFIG_RADIO_MAXIRADIO=m
-CONFIG_RADIO_MAESTRO=m
-CONFIG_RADIO_MIROPCM20=m
-CONFIG_RADIO_MIROPCM20_RDS=m
-CONFIG_RADIO_SF16FMI=m
-CONFIG_RADIO_SF16FMR2=m
-CONFIG_RADIO_TERRATEC=m
-CONFIG_RADIO_TRUST=m
-CONFIG_RADIO_TYPHOON=m
-CONFIG_RADIO_TYPHOON_PROC_FS=y
-CONFIG_RADIO_ZOLTRIX=m
-
-#
-# Crypto Hardware support
-#
-CONFIG_CRYPTO=m
-CONFIG_CRYPTO_BROADCOM=m
-
-#
-# File systems
-#
-CONFIG_QUOTA=y
-# CONFIG_QFMT_V1 is not set
-CONFIG_QFMT_V2=y
-# CONFIG_QIFACE_COMPAT is not set
-CONFIG_AUTOFS_FS=m
-CONFIG_AUTOFS4_FS=m
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-CONFIG_REISERFS_PROC_INFO=y
-# CONFIG_ADFS_FS is not set
-CONFIG_AFS_FS=m
-# CONFIG_ADFS_FS_RW is not set
-# CONFIG_AFFS_FS is not set
-CONFIG_HFS_FS=m
-CONFIG_BEFS_FS=m
-# CONFIG_BEFS_DEBUG is not set
-CONFIG_BFS_FS=m
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-CONFIG_EXT3_FS_XATTR_SHARING=y
-CONFIG_EXT3_FS_XATTR_USER=y
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_UMSDOS_FS=m
-CONFIG_VFAT_FS=m
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-CONFIG_CRAMFS=m
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_JFS_FS=m
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
-CONFIG_MINIX_FS=m
-CONFIG_VXFS_FS=m
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_RW is not set
-# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-CONFIG_ROMFS_FS=m
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_XATTR_SHARING=y
-CONFIG_EXT2_FS_XATTR_USER=y
-CONFIG_SYSV_FS=m
-CONFIG_UDF_FS=m
-CONFIG_UDF_RW=y
-CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
-
-#
-# Network File Systems
-#
-CONFIG_CODA_FS=m
-CONFIG_INTERMEZZO_FS=m
-CONFIG_NFS_FS=m
-CONFIG_NFS_V3=y
-# CONFIG_ROOT_NFS is not set
-CONFIG_NFSD=m
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_TCP is not set
-CONFIG_SUNRPC=m
-CONFIG_LOCKD=m
-CONFIG_LOCKD_V4=y
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
-CONFIG_NCP_FS=m
-CONFIG_NCPFS_PACKET_SIGNING=y
-CONFIG_NCPFS_IOCTL_LOCKING=y
-CONFIG_NCPFS_STRONG=y
-CONFIG_NCPFS_NFS_NS=y
-CONFIG_NCPFS_OS2_NS=y
-CONFIG_NCPFS_SMALLDOS=y
-CONFIG_NCPFS_NLS=y
-CONFIG_NCPFS_EXTRAS=y
-CONFIG_ZISOFS_FS=y
-CONFIG_FS_MBCACHE=y
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-CONFIG_OSF_PARTITION=y
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
-CONFIG_BSD_DISKLABEL=y
-CONFIG_MINIX_SUBPARTITION=y
-CONFIG_SOLARIS_X86_PARTITION=y
-CONFIG_UNIXWARE_DISKLABEL=y
-# CONFIG_LDM_PARTITION is not set
-CONFIG_SGI_PARTITION=y
-# CONFIG_ULTRIX_PARTITION is not set
-CONFIG_SUN_PARTITION=y
-# CONFIG_EFI_PARTITION is not set
-CONFIG_SMB_NLS=y
-CONFIG_NLS=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=m
-
-#
-# Console drivers
-#
-CONFIG_VGA_CONSOLE=y
-CONFIG_VIDEO_SELECT=y
-# CONFIG_VIDEO_IGNORE_BAD_MODE is not set
-CONFIG_MDA_CONSOLE=m
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FB_RIVA=m
-CONFIG_FB_CLGEN=m
-CONFIG_FB_PM2=m
-# CONFIG_FB_PM2_FIFO_DISCONNECT is not set
-CONFIG_FB_PM2_PCI=y
-CONFIG_FB_PM3=m
-# CONFIG_FB_CYBER2000 is not set
-CONFIG_FB_VESA=y
-CONFIG_FB_VGA16=m
-CONFIG_FB_HGA=m
-CONFIG_VIDEO_SELECT=y
-CONFIG_FB_MATROX=m
-CONFIG_FB_MATROX_MILLENIUM=y
-CONFIG_FB_MATROX_MYSTIQUE=y
-# CONFIG_FB_MATROX_G450 is not set
-CONFIG_FB_MATROX_G100A=y
-CONFIG_FB_MATROX_G100=y
-CONFIG_FB_MATROX_I2C=m
-CONFIG_FB_MATROX_MAVEN=m
-# CONFIG_FB_MATROX_PROC is not set
-CONFIG_FB_MATROX_MULTIHEAD=y
-CONFIG_FB_ATY=m
-CONFIG_FB_ATY_GX=y
-CONFIG_FB_ATY_CT=y
-CONFIG_FB_ATY_CT_VAIO_LCD=y
-CONFIG_FB_RADEON=m
-CONFIG_FB_ATY128=m
-CONFIG_FB_SIS=m
-CONFIG_FB_SIS_300=y
-CONFIG_FB_SIS_315=y
-CONFIG_FB_NEOMAGIC=m
-CONFIG_FB_3DFX=m
-CONFIG_FB_VOODOO1=m
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-# CONFIG_FBCON_ADVANCED is not set
-CONFIG_FBCON_MFB=m
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-CONFIG_FBCON_CFB24=y
-CONFIG_FBCON_CFB32=y
-CONFIG_FBCON_VGA_PLANES=m
-CONFIG_FBCON_HGA=m
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-# CONFIG_FBCON_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Sound
-#
-CONFIG_SOUND=m
-CONFIG_SOUND_ALI5455=m
-CONFIG_SOUND_BT878=m
-CONFIG_SOUND_CMPCI=m
-CONFIG_SOUND_CMPCI_FM=y
-CONFIG_SOUND_CMPCI_FMIO=388
-CONFIG_SOUND_CMPCI_FMIO=388
-CONFIG_SOUND_CMPCI_MIDI=y
-CONFIG_SOUND_CMPCI_MPUIO=330
-CONFIG_SOUND_CMPCI_JOYSTICK=y
-CONFIG_SOUND_CMPCI_CM8738=y
-# CONFIG_SOUND_CMPCI_SPDIFINVERSE is not set
-CONFIG_SOUND_CMPCI_SPDIFLOOP=y
-CONFIG_SOUND_CMPCI_SPEAKERS=2
-CONFIG_SOUND_EMU10K1=m
-CONFIG_MIDI_EMU10K1=y
-CONFIG_SOUND_AUDIGY=m
-CONFIG_SOUND_FUSION=m
-CONFIG_SOUND_CS4281=m
-CONFIG_SOUND_ES1370=m
-CONFIG_SOUND_ES1371=m
-CONFIG_SOUND_ESSSOLO1=m
-CONFIG_SOUND_MAESTRO=m
-CONFIG_SOUND_MAESTRO3=m
-CONFIG_SOUND_FORTE=m
-CONFIG_SOUND_ICH=m
-CONFIG_SOUND_RME96XX=m
-CONFIG_SOUND_SONICVIBES=m
-CONFIG_SOUND_TRIDENT=m
-CONFIG_SOUND_MSNDCLAS=m
-# CONFIG_MSNDCLAS_HAVE_BOOT is not set
-CONFIG_MSNDCLAS_INIT_FILE="/etc/sound/msndinit.bin"
-CONFIG_MSNDCLAS_PERM_FILE="/etc/sound/msndperm.bin"
-CONFIG_SOUND_MSNDPIN=m
-# CONFIG_MSNDPIN_HAVE_BOOT is not set
-CONFIG_MSNDPIN_INIT_FILE="/etc/sound/pndspini.bin"
-CONFIG_MSNDPIN_PERM_FILE="/etc/sound/pndsperm.bin"
-CONFIG_SOUND_VIA82CXXX=m
-CONFIG_MIDI_VIA82CXXX=y
-CONFIG_SOUND_OSS=m
-# CONFIG_SOUND_TRACEINIT is not set
-CONFIG_SOUND_DMAP=y
-CONFIG_SOUND_AD1816=m
-CONFIG_SOUND_AD1889=m
-CONFIG_SOUND_SGALAXY=m
-CONFIG_SOUND_ADLIB=m
-CONFIG_SOUND_ACI_MIXER=m
-CONFIG_SOUND_CS4232=m
-CONFIG_SOUND_SSCAPE=m
-CONFIG_SOUND_GUS=m
-CONFIG_SOUND_GUS16=y
-CONFIG_SOUND_GUSMAX=y
-CONFIG_SOUND_VMIDI=m
-CONFIG_SOUND_TRIX=m
-CONFIG_SOUND_MSS=m
-CONFIG_SOUND_MPU401=m
-CONFIG_SOUND_NM256=m
-CONFIG_SOUND_MAD16=m
-CONFIG_MAD16_OLDCARD=y
-CONFIG_SOUND_PAS=m
-# CONFIG_PAS_JOYSTICK is not set
-CONFIG_SOUND_PSS=m
-# CONFIG_PSS_MIXER is not set
-# CONFIG_PSS_HAVE_BOOT is not set
-CONFIG_SOUND_SB=m
-CONFIG_SOUND_AWE32_SYNTH=m
-CONFIG_SOUND_KAHLUA=m
-CONFIG_SOUND_WAVEFRONT=m
-CONFIG_SOUND_MAUI=m
-CONFIG_SOUND_YM3812=m
-CONFIG_SOUND_OPL3SA1=m
-CONFIG_SOUND_OPL3SA2=m
-CONFIG_SOUND_YMFPCI=m
-CONFIG_SOUND_YMFPCI_LEGACY=y
-CONFIG_SOUND_UART6850=m
-CONFIG_SOUND_AEDSP16=m
-CONFIG_SC6600=y
-CONFIG_SC6600_JOY=y
-CONFIG_SC6600_CDROM=4
-CONFIG_SC6600_CDROMBASE=0
-CONFIG_AEDSP16_SBPRO=y
-CONFIG_AEDSP16_MPU401=y
-CONFIG_SOUND_TVMIXER=m
-
-#
-# USB support
-#
-CONFIG_USB=m
-# CONFIG_USB_DEBUG is not set
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
-CONFIG_USB_EHCI_HCD=m
-CONFIG_USB_UHCI=m
-CONFIG_USB_UHCI_ALT=m
-CONFIG_USB_OHCI=m
-CONFIG_USB_AUDIO=m
-# CONFIG_USB_EMI26 is not set
-CONFIG_USB_MIDI=m
-CONFIG_USB_STORAGE=m
-# CONFIG_USB_STORAGE_DEBUG is not set
-CONFIG_USB_STORAGE_DATAFAB=y
-CONFIG_USB_STORAGE_FREECOM=y
-CONFIG_USB_STORAGE_ISD200=y
-CONFIG_USB_STORAGE_DPCM=y
-CONFIG_USB_STORAGE_HP8200e=y
-CONFIG_USB_STORAGE_SDDR09=y
-CONFIG_USB_STORAGE_SDDR55=y
-CONFIG_USB_STORAGE_JUMPSHOT=y
-CONFIG_USB_ACM=m
-CONFIG_USB_PRINTER=m
-CONFIG_USB_HID=m
-CONFIG_USB_HIDINPUT=y
-CONFIG_USB_HIDDEV=y
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
-CONFIG_USB_AIPTEK=m
-CONFIG_USB_WACOM=m
-CONFIG_USB_KBTAB=m
-CONFIG_USB_POWERMATE=m
-# CONFIG_USB_DC2XX is not set
-CONFIG_USB_MDC800=m
-CONFIG_USB_SCANNER=m
-CONFIG_USB_MICROTEK=m
-CONFIG_USB_HPUSBSCSI=m
-CONFIG_USB_IBMCAM=m
-CONFIG_USB_KONICAWC=m
-CONFIG_USB_OV511=m
-CONFIG_USB_PWC=m
-CONFIG_USB_SE401=m
-CONFIG_USB_STV680=m
-CONFIG_USB_VICAM=m
-CONFIG_USB_DSBR=m
-CONFIG_USB_DABUSB=m
-CONFIG_USB_PEGASUS=m
-CONFIG_USB_RTL8150=m
-CONFIG_USB_KAWETH=m
-CONFIG_USB_CATC=m
-CONFIG_USB_CDCETHER=m
-CONFIG_USB_USBNET=m
-CONFIG_USB_USS720=m
-
-#
-# USB Serial Converter support
-#
-CONFIG_USB_SERIAL=m
-# CONFIG_USB_SERIAL_DEBUG is not set
-CONFIG_USB_SERIAL_GENERIC=y
-CONFIG_USB_SERIAL_BELKIN=m
-CONFIG_USB_SERIAL_WHITEHEAT=m
-CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
-CONFIG_USB_SERIAL_EMPEG=m
-CONFIG_USB_SERIAL_FTDI_SIO=m
-CONFIG_USB_SERIAL_VISOR=m
-CONFIG_USB_SERIAL_IPAQ=m
-CONFIG_USB_SERIAL_IR=m
-CONFIG_USB_SERIAL_EDGEPORT=m
-CONFIG_USB_SERIAL_EDGEPORT_TI=m
-CONFIG_USB_SERIAL_KEYSPAN_PDA=m
-CONFIG_USB_SERIAL_KEYSPAN=m
-# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
-CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
-# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
-CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
-CONFIG_USB_SERIAL_KEYSPAN_MPR=y
-CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
-CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
-CONFIG_USB_SERIAL_MCT_U232=m
-CONFIG_USB_SERIAL_KLSI=m
-CONFIG_USB_SERIAL_KOBIL_SCT=m
-CONFIG_USB_SERIAL_PL2303=m
-CONFIG_USB_SERIAL_CYBERJACK=m
-CONFIG_USB_SERIAL_XIRCOM=m
-CONFIG_USB_SERIAL_OMNINET=m
-CONFIG_USB_RIO500=m
-CONFIG_USB_AUERSWALD=m
-CONFIG_USB_TIGL=m
-CONFIG_USB_BRLVGER=m
-CONFIG_USB_LCD=m
-
-#
-# Additional device driver support
-#
-CONFIG_NET_BROADCOM=m
-CONFIG_CIPE=m
-CONFIG_CRYPTO_AEP=m
-CONFIG_MEGARAC=m
-CONFIG_FC_QLA2200=m
-CONFIG_FC_QLA2300=m
-CONFIG_SCSI_ISCSI=m
-
-#
-# Bluetooth support
-#
-CONFIG_BLUEZ=m
-CONFIG_BLUEZ_L2CAP=m
-CONFIG_BLUEZ_SCO=m
-CONFIG_BLUEZ_RFCOMM=m
-CONFIG_BLUEZ_RFCOMM_TTY=y
-CONFIG_BLUEZ_BNEP=m
-CONFIG_BLUEZ_BNEP_MC_FILTER=y
-CONFIG_BLUEZ_BNEP_PROTO_FILTER=y
-
-#
-# Bluetooth device drivers
-#
-CONFIG_BLUEZ_HCIUSB=m
-CONFIG_BLUEZ_USB_SCO=y
-CONFIG_BLUEZ_USB_ZERO_PACKET=y
-CONFIG_BLUEZ_HCIUART=m
-CONFIG_BLUEZ_HCIUART_H4=y
-CONFIG_BLUEZ_HCIUART_BCSP=y
-CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y
-CONFIG_BLUEZ_HCIDTL1=m
-CONFIG_BLUEZ_HCIBT3C=m
-CONFIG_BLUEZ_HCIBLUECARD=m
-CONFIG_BLUEZ_HCIBTUART=m
-CONFIG_BLUEZ_HCIVHCI=m
-
-#
-# Profiling support
-#
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=m
-
-#
-# Kernel hacking
-#
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_STACKOVERFLOW is not set
-# CONFIG_DEBUG_HIGHMEM is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_IOVIRT is not set
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_DEBUG_SPINLOCK is not set
-CONFIG_FRAME_POINTER=y
-# CONFIG_MCL_COREDUMP is not set
-
-#
-# Library routines
-#
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=m
+++ /dev/null
-#
-# Automatically generated by make menuconfig: don't edit
-#
-CONFIG_X86=y
-# CONFIG_SBUS is not set
-CONFIG_UID16=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Processor type and features
-#
-# CONFIG_LOLAT is not set
-# CONFIG_M386 is not set
-# CONFIG_M486 is not set
-CONFIG_M586=y
-# CONFIG_M586TSC is not set
-# CONFIG_M586MMX is not set
-# CONFIG_M686 is not set
-# CONFIG_MPENTIUMIII is not set
-# CONFIG_MPENTIUM4 is not set
-# CONFIG_MK6 is not set
-# CONFIG_MK7 is not set
-# CONFIG_MELAN is not set
-# CONFIG_MCRUSOE is not set
-# CONFIG_MWINCHIPC6 is not set
-# CONFIG_MWINCHIP2 is not set
-# CONFIG_MWINCHIP3D is not set
-# CONFIG_MCYRIXIII is not set
-CONFIG_X86_WP_WORKS_OK=y
-CONFIG_X86_INVLPG=y
-CONFIG_X86_CMPXCHG=y
-CONFIG_X86_XADD=y
-CONFIG_X86_BSWAP=y
-CONFIG_X86_POPAD_OK=y
-# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_X86_L1_CACHE_SHIFT=5
-CONFIG_X86_USE_STRING_486=y
-CONFIG_X86_ALIGNMENT_16=y
-CONFIG_X86_PPRO_FENCE=y
-# CONFIG_X86_F00F_WORKS_OK is not set
-CONFIG_X86_MCE=y
-
-#
-# CPU Frequency scaling
-#
-# CONFIG_CPU_FREQ is not set
-CONFIG_TOSHIBA=m
-CONFIG_I8K=m
-CONFIG_MICROCODE=m
-CONFIG_X86_MSR=m
-CONFIG_X86_CPUID=m
-# CONFIG_E820_PROC is not set
-CONFIG_EDD=m
-# CONFIG_NOHIGHMEM is not set
-CONFIG_HIGHMEM4G=y
-# CONFIG_HIGHMEM64G is not set
-CONFIG_HIGHMEM=y
-CONFIG_HIGHPTE=y
-CONFIG_HIGHIO=y
-# CONFIG_MATH_EMULATION is not set
-CONFIG_MTRR=y
-CONFIG_SMP=y
-# CONFIG_X86_NUMA is not set
-# CONFIG_X86_TSC_DISABLE is not set
-CONFIG_HAVE_DEC_LOCK=y
-# CONFIG_NOBIGSTACK is not set
-CONFIG_STACK_SIZE_16KB=y
-# CONFIG_STACK_SIZE_32KB is not set
-# CONFIG_STACK_SIZE_64KB is not set
-CONFIG_STACK_SIZE_SHIFT=2
-
-#
-# General setup
-#
-CONFIG_NET=y
-CONFIG_X86_IO_APIC=y
-CONFIG_X86_LOCAL_APIC=y
-CONFIG_PCI=y
-# CONFIG_PCI_GOBIOS is not set
-# CONFIG_PCI_GODIRECT is not set
-CONFIG_PCI_GOANY=y
-CONFIG_PCI_BIOS=y
-CONFIG_PCI_DIRECT=y
-CONFIG_ISA=y
-CONFIG_PCI_NAMES=y
-CONFIG_EISA=y
-# CONFIG_MCA is not set
-CONFIG_HOTPLUG=y
-
-#
-# PCMCIA/CardBus support
-#
-CONFIG_PCMCIA=m
-CONFIG_CARDBUS=y
-CONFIG_TCIC=y
-CONFIG_I82092=y
-CONFIG_I82365=y
-
-#
-# PCI Hotplug Support
-#
-CONFIG_HOTPLUG_PCI=y
-# CONFIG_HOTPLUG_PCI_ACPI is not set
-CONFIG_HOTPLUG_PCI_COMPAQ=m
-# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
-CONFIG_HOTPLUG_PCI_IBM=m
-# CONFIG_HOTPLUG_PCI_H2999 is not set
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=m
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=m
-CONFIG_PM=y
-# CONFIG_ACPI is not set
-CONFIG_APM=y
-# CONFIG_APM_IGNORE_USER_SUSPEND is not set
-# CONFIG_APM_DO_ENABLE is not set
-CONFIG_APM_CPU_IDLE=y
-# CONFIG_APM_DISPLAY_BLANK is not set
-CONFIG_APM_RTC_IS_GMT=y
-# CONFIG_APM_ALLOW_INTS is not set
-# CONFIG_APM_REAL_MODE_POWER_OFF is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-CONFIG_PARPORT=m
-CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_CML1=m
-CONFIG_PARPORT_SERIAL=m
-# CONFIG_PARPORT_PC_FIFO is not set
-# CONFIG_PARPORT_PC_SUPERIO is not set
-CONFIG_PARPORT_PC_PCMCIA=m
-# CONFIG_PARPORT_AMIGA is not set
-# CONFIG_PARPORT_MFC3 is not set
-# CONFIG_PARPORT_ATARI is not set
-# CONFIG_PARPORT_GSC is not set
-# CONFIG_PARPORT_SUNBPP is not set
-# CONFIG_PARPORT_OTHER is not set
-CONFIG_PARPORT_1284=y
-
-#
-# Plug and Play configuration
-#
-CONFIG_PNP=y
-CONFIG_ISAPNP=y
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_FD=y
-CONFIG_BLK_DEV_XD=m
-CONFIG_PARIDE=m
-CONFIG_PARIDE_PARPORT=m
-CONFIG_PARIDE_PD=m
-CONFIG_PARIDE_PCD=m
-CONFIG_PARIDE_PF=m
-CONFIG_PARIDE_PT=m
-CONFIG_PARIDE_PG=m
-CONFIG_PARIDE_ATEN=m
-CONFIG_PARIDE_BPCK=m
-CONFIG_PARIDE_BPCK6=m
-CONFIG_PARIDE_COMM=m
-CONFIG_PARIDE_DSTR=m
-CONFIG_PARIDE_FIT2=m
-CONFIG_PARIDE_FIT3=m
-CONFIG_PARIDE_EPAT=m
-CONFIG_PARIDE_EPATC8=y
-CONFIG_PARIDE_EPIA=m
-CONFIG_PARIDE_FRIQ=m
-CONFIG_PARIDE_FRPW=m
-CONFIG_PARIDE_KBIC=m
-CONFIG_PARIDE_KTTI=m
-CONFIG_PARIDE_ON20=m
-CONFIG_PARIDE_ON26=m
-CONFIG_BLK_CPQ_DA=m
-CONFIG_BLK_CPQ_CISS_DA=m
-CONFIG_CISS_SCSI_TAPE=y
-CONFIG_BLK_DEV_DAC960=m
-CONFIG_BLK_DEV_UMEM=m
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_BLK_STATS=y
-
-#
-# Multi-device support (RAID and LVM)
-#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=m
-CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_RAID5=m
-CONFIG_MD_MULTIPATH=m
-CONFIG_BLK_DEV_LVM=m
-
-#
-# Cryptography support (CryptoAPI)
-#
-CONFIG_CRYPTO=m
-CONFIG_CIPHERS=m
-CONFIG_CIPHER_AES=m
-CONFIG_CIPHER_IDENTITY=m
-CONFIG_CRYPTODEV=m
-CONFIG_CRYPTOLOOP=m
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_FILTER=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_TUX=m
-CONFIG_TUX_EXTCGI=y
-# CONFIG_TUX_EXTENDED_LOG is not set
-# CONFIG_TUX_DEBUG is not set
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_FWMARK=y
-CONFIG_IP_ROUTE_NAT=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_TOS=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_ROUTE_LARGE_TABLES=y
-# CONFIG_IP_PNP is not set
-CONFIG_NET_IPIP=m
-CONFIG_NET_IPGRE=m
-CONFIG_NET_IPGRE_BROADCAST=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-CONFIG_SYN_COOKIES=y
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_UNCLEAN=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_MIRROR=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_NAT_LOCAL=y
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_COMPAT_IPFWADM=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IPV6=m
-
-#
-# IPv6: Netfilter Configuration
-#
-# CONFIG_IP6_NF_QUEUE is not set
-CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_LIMIT=m
-CONFIG_IP6_NF_MATCH_MAC=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
-CONFIG_IP6_NF_MATCH_FRAG=m
-CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
-CONFIG_IP6_NF_MATCH_OWNER=m
-CONFIG_IP6_NF_MATCH_MARK=m
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
-CONFIG_IP6_NF_MATCH_LENGTH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=m
-CONFIG_IP6_NF_TARGET_LOG=m
-CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_MARK=m
-# CONFIG_KHTTPD is not set
-CONFIG_ATM=y
-CONFIG_ATM_CLIP=y
-# CONFIG_ATM_CLIP_NO_ICMP is not set
-CONFIG_ATM_LANE=m
-CONFIG_ATM_MPOA=m
-CONFIG_ATM_BR2684=m
-CONFIG_ATM_BR2684_IPFILTER=y
-CONFIG_VLAN_8021Q=m
-CONFIG_IPX=m
-# CONFIG_IPX_INTERN is not set
-CONFIG_ATALK=m
-
-#
-# Appletalk devices
-#
-CONFIG_DEV_APPLETALK=y
-CONFIG_LTPC=m
-CONFIG_COPS=m
-CONFIG_COPS_DAYNA=y
-CONFIG_COPS_TANGENT=y
-CONFIG_IPDDP=m
-CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
-CONFIG_DECNET=m
-CONFIG_DECNET_SIOCGIFCONF=y
-CONFIG_DECNET_ROUTER=y
-CONFIG_DECNET_ROUTE_FWMARK=y
-CONFIG_BRIDGE=m
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
-CONFIG_NET_DIVERT=y
-# CONFIG_ECONET is not set
-CONFIG_WAN_ROUTER=m
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_CBQ=m
-CONFIG_NET_SCH_HTB=m
-CONFIG_NET_SCH_CSZ=m
-# CONFIG_NET_SCH_ATM is not set
-CONFIG_NET_SCH_PRIO=m
-CONFIG_NET_SCH_RED=m
-CONFIG_NET_SCH_SFQ=m
-CONFIG_NET_SCH_TEQL=m
-CONFIG_NET_SCH_TBF=m
-CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DSMARK=m
-CONFIG_NET_SCH_INGRESS=m
-CONFIG_NET_QOS=y
-CONFIG_NET_ESTIMATOR=y
-CONFIG_NET_CLS=y
-CONFIG_NET_CLS_TCINDEX=m
-CONFIG_NET_CLS_ROUTE4=m
-CONFIG_NET_CLS_ROUTE=y
-CONFIG_NET_CLS_FW=m
-CONFIG_NET_CLS_U32=m
-CONFIG_NET_CLS_RSVP=m
-CONFIG_NET_CLS_RSVP6=m
-CONFIG_NET_CLS_POLICE=y
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-
-#
-# Telephony Support
-#
-CONFIG_PHONE=m
-CONFIG_PHONE_IXJ=m
-CONFIG_PHONE_IXJ_PCMCIA=m
-
-#
-# ATA/IDE/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-# CONFIG_BLK_DEV_HD_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_IDEDISK_MULTI_MODE=y
-# CONFIG_IDEDISK_STROKE is not set
-CONFIG_BLK_DEV_IDECS=m
-CONFIG_BLK_DEV_IDECD=m
-CONFIG_BLK_DEV_IDETAPE=m
-CONFIG_BLK_DEV_IDEFLOPPY=y
-CONFIG_BLK_DEV_IDESCSI=m
-# CONFIG_IDE_TASK_IOCTL is not set
-CONFIG_BLK_DEV_CMD640=y
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-CONFIG_BLK_DEV_ISAPNP=y
-CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_IDEPCI_SHARE_IRQ=y
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
-# CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_PCI_WIP is not set
-CONFIG_BLK_DEV_ADMA100=y
-CONFIG_BLK_DEV_AEC62XX=y
-CONFIG_BLK_DEV_ALI15X3=y
-# CONFIG_WDC_ALI15X3 is not set
-CONFIG_BLK_DEV_AMD74XX=y
-# CONFIG_AMD74XX_OVERRIDE is not set
-CONFIG_BLK_DEV_CMD64X=y
-CONFIG_BLK_DEV_TRIFLEX=y
-CONFIG_BLK_DEV_CY82C693=y
-CONFIG_BLK_DEV_CS5530=y
-CONFIG_BLK_DEV_HPT34X=y
-# CONFIG_HPT34X_AUTODMA is not set
-CONFIG_BLK_DEV_HPT366=y
-CONFIG_BLK_DEV_PIIX=y
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_PDC202XX_OLD=y
-# CONFIG_PDC202XX_BURST is not set
-CONFIG_BLK_DEV_PDC202XX_NEW=y
-CONFIG_PDC202XX_FORCE=y
-CONFIG_BLK_DEV_RZ1000=y
-# CONFIG_BLK_DEV_SC1200 is not set
-CONFIG_BLK_DEV_SVWKS=y
-CONFIG_BLK_DEV_SIIMAGE=y
-CONFIG_BLK_DEV_SIS5513=y
-CONFIG_BLK_DEV_SLC90E66=y
-# CONFIG_BLK_DEV_TRM290 is not set
-CONFIG_BLK_DEV_VIA82CXXX=y
-# CONFIG_IDE_CHIPSETS is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_DMA_NONPCI is not set
-CONFIG_BLK_DEV_PDC202XX=y
-CONFIG_BLK_DEV_IDE_MODES=y
-CONFIG_BLK_DEV_ATARAID=m
-CONFIG_BLK_DEV_ATARAID_PDC=m
-CONFIG_BLK_DEV_ATARAID_HPT=m
-CONFIG_BLK_DEV_ATARAID_SII=m
-
-#
-# SCSI support
-#
-CONFIG_SCSI=m
-CONFIG_BLK_DEV_SD=m
-CONFIG_SD_EXTRA_DEVS=40
-CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
-CONFIG_BLK_DEV_SR=m
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_SR_EXTRA_DEVS=4
-CONFIG_CHR_DEV_SG=m
-# CONFIG_SCSI_DEBUG_QUEUES is not set
-# CONFIG_SCSI_MULTI_LUN is not set
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-
-#
-# SCSI low-level drivers
-#
-CONFIG_BLK_DEV_3W_XXXX_RAID=m
-CONFIG_SCSI_7000FASST=m
-CONFIG_SCSI_ACARD=m
-CONFIG_SCSI_AHA152X=m
-CONFIG_SCSI_AHA1542=m
-CONFIG_SCSI_AHA1740=m
-CONFIG_SCSI_AACRAID=m
-CONFIG_SCSI_AIC7XXX=m
-CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
-CONFIG_AIC7XXX_RESET_DELAY_MS=15000
-# CONFIG_AIC7XXX_PROBE_EISA_VL is not set
-# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
-CONFIG_SCSI_AIC79XX=m
-CONFIG_AIC79XX_CMDS_PER_DEVICE=253
-CONFIG_AIC79XX_RESET_DELAY_MS=15000
-# CONFIG_AIC79XX_BUILD_FIRMWARE is not set
-CONFIG_AIC79XX_ENABLE_RD_STRM=y
-# CONFIG_AIC79XX_DEBUG_ENABLE is not set
-CONFIG_AIC79XX_DEBUG_MASK=0
-CONFIG_SCSI_AIC7XXX_OLD=m
-CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y
-CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=32
-CONFIG_AIC7XXX_OLD_PROC_STATS=y
-CONFIG_SCSI_DPT_I2O=m
-CONFIG_SCSI_ADVANSYS=m
-CONFIG_SCSI_IN2000=m
-CONFIG_SCSI_AM53C974=m
-CONFIG_SCSI_MEGARAID=m
-CONFIG_SCSI_BUSLOGIC=m
-# CONFIG_SCSI_OMIT_FLASHPOINT is not set
-CONFIG_SCSI_CPQFCTS=m
-CONFIG_SCSI_DMX3191D=m
-CONFIG_SCSI_DTC3280=m
-CONFIG_SCSI_EATA=m
-CONFIG_SCSI_EATA_TAGGED_QUEUE=y
-# CONFIG_SCSI_EATA_LINKED_COMMANDS is not set
-CONFIG_SCSI_EATA_MAX_TAGS=16
-CONFIG_SCSI_EATA_DMA=m
-CONFIG_SCSI_EATA_PIO=m
-CONFIG_SCSI_FUTURE_DOMAIN=m
-CONFIG_SCSI_GDTH=m
-CONFIG_SCSI_GENERIC_NCR5380=m
-# CONFIG_SCSI_GENERIC_NCR53C400 is not set
-CONFIG_SCSI_G_NCR5380_PORT=y
-# CONFIG_SCSI_G_NCR5380_MEM is not set
-CONFIG_SCSI_IPS=m
-CONFIG_SCSI_INITIO=m
-CONFIG_SCSI_INIA100=m
-CONFIG_SCSI_PPA=m
-CONFIG_SCSI_IMM=m
-# CONFIG_SCSI_IZIP_EPP16 is not set
-# CONFIG_SCSI_IZIP_SLOW_CTR is not set
-CONFIG_SCSI_NCR53C406A=m
-CONFIG_SCSI_NCR53C7xx=m
-# CONFIG_SCSI_NCR53C7xx_sync is not set
-CONFIG_SCSI_NCR53C7xx_FAST=y
-CONFIG_SCSI_NCR53C7xx_DISCONNECT=y
-CONFIG_SCSI_SYM53C8XX_2=m
-CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
-CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
-CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
-CONFIG_SCSI_NCR53C8XX=m
-CONFIG_SCSI_SYM53C8XX=m
-CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
-CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
-CONFIG_SCSI_NCR53C8XX_SYNC=40
-# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
-# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set
-# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
-CONFIG_SCSI_PAS16=m
-CONFIG_SCSI_PCI2000=m
-CONFIG_SCSI_PCI2220I=m
-CONFIG_SCSI_PSI240I=m
-CONFIG_SCSI_QLOGIC_FAS=m
-CONFIG_SCSI_QLOGIC_ISP=m
-CONFIG_SCSI_QLOGIC_FC=m
-# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
-CONFIG_SCSI_QLOGIC_1280=m
-CONFIG_SCSI_NEWISP=m
-CONFIG_SCSI_SEAGATE=m
-CONFIG_SCSI_SIM710=m
-CONFIG_SCSI_SYM53C416=m
-CONFIG_SCSI_DC390T=m
-# CONFIG_SCSI_DC390T_NOGENSUPP is not set
-CONFIG_SCSI_T128=m
-CONFIG_SCSI_U14_34F=m
-# CONFIG_SCSI_U14_34F_LINKED_COMMANDS is not set
-CONFIG_SCSI_U14_34F_MAX_TAGS=8
-CONFIG_SCSI_ULTRASTOR=m
-CONFIG_SCSI_NSP32=m
-CONFIG_SCSI_DEBUG=m
-
-#
-# PCMCIA SCSI adapter support
-#
-CONFIG_SCSI_PCMCIA=y
-CONFIG_PCMCIA_AHA152X=m
-CONFIG_PCMCIA_FDOMAIN=m
-CONFIG_PCMCIA_NINJA_SCSI=m
-CONFIG_PCMCIA_QLOGIC=m
-
-#
-# Fusion MPT device support
-#
-CONFIG_FUSION=m
-# CONFIG_FUSION_BOOT is not set
-CONFIG_FUSION_MAX_SGE=40
-# CONFIG_FUSION_ISENSE is not set
-CONFIG_FUSION_CTL=m
-CONFIG_FUSION_LAN=m
-CONFIG_NET_FC=y
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-CONFIG_IEEE1394=m
-# CONFIG_IEEE1394_PCILYNX is not set
-CONFIG_IEEE1394_OHCI1394=m
-CONFIG_IEEE1394_VIDEO1394=m
-CONFIG_IEEE1394_SBP2=m
-CONFIG_IEEE1394_SBP2_PHYS_DMA=y
-CONFIG_IEEE1394_ETH1394=m
-CONFIG_IEEE1394_DV1394=m
-CONFIG_IEEE1394_RAWIO=m
-CONFIG_IEEE1394_CMP=m
-CONFIG_IEEE1394_AMDTP=m
-# CONFIG_IEEE1394_VERBOSEDEBUG is not set
-
-#
-# I2O device support
-#
-CONFIG_I2O=m
-CONFIG_I2O_PCI=m
-CONFIG_I2O_BLOCK=m
-CONFIG_I2O_LAN=m
-CONFIG_I2O_SCSI=m
-CONFIG_I2O_PROC=m
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-CONFIG_DUMMY=m
-CONFIG_BONDING=m
-CONFIG_EQUALIZER=m
-CONFIG_TUN=m
-CONFIG_ETHERTAP=m
-CONFIG_NET_SB1000=m
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_SUNLANCE is not set
-CONFIG_HAPPYMEAL=m
-# CONFIG_SUNBMAC is not set
-# CONFIG_SUNQE is not set
-CONFIG_SUNGEM=m
-CONFIG_NET_VENDOR_3COM=y
-CONFIG_EL1=m
-CONFIG_EL2=m
-CONFIG_ELPLUS=m
-CONFIG_EL16=m
-CONFIG_EL3=m
-CONFIG_3C515=m
-# CONFIG_ELMC is not set
-# CONFIG_ELMC_II is not set
-CONFIG_VORTEX=m
-CONFIG_TYPHOON=m
-CONFIG_LANCE=m
-CONFIG_NET_VENDOR_SMC=y
-CONFIG_WD80x3=m
-# CONFIG_ULTRAMCA is not set
-CONFIG_ULTRA=m
-CONFIG_ULTRA32=m
-CONFIG_SMC9194=m
-CONFIG_NET_VENDOR_RACAL=y
-CONFIG_NI5010=m
-CONFIG_NI52=m
-CONFIG_NI65=m
-CONFIG_AT1700=m
-CONFIG_DEPCA=m
-CONFIG_HP100=m
-CONFIG_NET_ISA=y
-CONFIG_E2100=m
-# CONFIG_EWRK3 is not set
-CONFIG_EEXPRESS=m
-CONFIG_EEXPRESS_PRO=m
-CONFIG_HPLAN_PLUS=m
-CONFIG_HPLAN=m
-CONFIG_LP486E=m
-CONFIG_ETH16I=m
-CONFIG_NE2000=m
-CONFIG_NET_PCI=y
-CONFIG_PCNET32=m
-CONFIG_AMD8111_ETH=m
-CONFIG_ADAPTEC_STARFIRE=m
-CONFIG_AC3200=m
-CONFIG_APRICOT=m
-CONFIG_CS89x0=m
-CONFIG_TULIP=m
-# CONFIG_TULIP_MWI is not set
-CONFIG_TULIP_MMIO=y
-CONFIG_DE4X5=m
-CONFIG_DGRS=m
-CONFIG_DM9102=m
-CONFIG_EEPRO100=m
-# CONFIG_EEPRO100_PIO is not set
-CONFIG_E100=m
-CONFIG_LNE390=m
-CONFIG_FEALNX=m
-CONFIG_NATSEMI=m
-CONFIG_NE2K_PCI=m
-CONFIG_NE3210=m
-CONFIG_ES3210=m
-CONFIG_8139CP=m
-CONFIG_8139TOO=m
-# CONFIG_8139TOO_PIO is not set
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-CONFIG_8139TOO_8129=y
-# CONFIG_8139_OLD_RX_RESET is not set
-CONFIG_SIS900=m
-CONFIG_EPIC100=m
-CONFIG_SUNDANCE=m
-# CONFIG_SUNDANCE_MMIO is not set
-CONFIG_TLAN=m
-CONFIG_TC35815=m
-CONFIG_VIA_RHINE=m
-# CONFIG_VIA_RHINE_MMIO is not set
-CONFIG_WINBOND_840=m
-CONFIG_NET_POCKET=y
-CONFIG_ATP=m
-CONFIG_DE600=m
-CONFIG_DE620=m
-
-#
-# Ethernet (1000 Mbit)
-#
-CONFIG_ACENIC=m
-# CONFIG_ACENIC_OMIT_TIGON_I is not set
-CONFIG_DL2K=m
-CONFIG_E1000=m
-# CONFIG_MYRI_SBUS is not set
-CONFIG_NS83820=m
-CONFIG_HAMACHI=m
-CONFIG_YELLOWFIN=m
-CONFIG_R8169=m
-CONFIG_SK98LIN=m
-CONFIG_TIGON3=m
-CONFIG_FDDI=y
-CONFIG_DEFXX=m
-CONFIG_SKFP=m
-CONFIG_NETCONSOLE=m
-# CONFIG_HIPPI is not set
-CONFIG_PLIP=m
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-# CONFIG_PPP_BSDCOMP is not set
-CONFIG_PPPOE=m
-CONFIG_PPPOATM=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-CONFIG_SLIP_MODE_SLIP6=y
-
-#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-CONFIG_STRIP=m
-CONFIG_WAVELAN=m
-CONFIG_ARLAN=m
-CONFIG_AIRONET4500=m
-CONFIG_AIRONET4500_NONCS=m
-CONFIG_AIRONET4500_PNP=y
-CONFIG_AIRONET4500_PCI=y
-CONFIG_AIRONET4500_ISA=y
-CONFIG_AIRONET4500_I365=y
-CONFIG_AIRONET4500_PROC=m
-CONFIG_AIRO=m
-CONFIG_HERMES=m
-CONFIG_PLX_HERMES=m
-CONFIG_PCI_HERMES=m
-CONFIG_PCMCIA_HERMES=m
-CONFIG_AIRO_CS=m
-CONFIG_NET_WIRELESS=y
-CONFIG_PCMCIA_HERMES_OLD=m
-
-#
-# Token Ring devices
-#
-CONFIG_TR=y
-CONFIG_IBMTR=m
-CONFIG_IBMOL=m
-CONFIG_IBMLS=m
-CONFIG_3C359=m
-CONFIG_TMS380TR=m
-CONFIG_TMSPCI=m
-CONFIG_TMSISA=m
-CONFIG_ABYSS=m
-# CONFIG_MADGEMC is not set
-CONFIG_SMCTR=m
-CONFIG_NET_FC=y
-CONFIG_IPHASE5526=m
-CONFIG_RCPCI=m
-CONFIG_SHAPER=m
-
-#
-# Wan interfaces
-#
-CONFIG_WAN=y
-CONFIG_HOSTESS_SV11=m
-CONFIG_COSA=m
-# CONFIG_COMX is not set
-# CONFIG_DSCC4 is not set
-# CONFIG_LANMEDIA is not set
-CONFIG_ATI_XX20=m
-CONFIG_SEALEVEL_4021=m
-# CONFIG_SYNCLINK_SYNCPPP is not set
-# CONFIG_HDLC is not set
-CONFIG_DLCI=m
-CONFIG_DLCI_COUNT=24
-CONFIG_DLCI_MAX=8
-CONFIG_SDLA=m
-CONFIG_WAN_ROUTER_DRIVERS=y
-CONFIG_VENDOR_SANGOMA=m
-CONFIG_WANPIPE_CHDLC=y
-CONFIG_WANPIPE_FR=y
-CONFIG_WANPIPE_X25=y
-CONFIG_WANPIPE_PPP=y
-CONFIG_WANPIPE_MULTPPP=y
-CONFIG_CYCLADES_SYNC=m
-CONFIG_CYCLOMX_X25=y
-# CONFIG_LAPBETHER is not set
-# CONFIG_X25_ASY is not set
-CONFIG_SBNI=m
-CONFIG_SBNI_MULTILINE=y
-
-#
-# PCMCIA network device support
-#
-CONFIG_NET_PCMCIA=y
-CONFIG_PCMCIA_3C589=m
-CONFIG_PCMCIA_3C574=m
-CONFIG_PCMCIA_FMVJ18X=m
-CONFIG_PCMCIA_PCNET=m
-CONFIG_PCMCIA_AXNET=m
-CONFIG_PCMCIA_NMCLAN=m
-CONFIG_PCMCIA_SMC91C92=m
-CONFIG_PCMCIA_XIRC2PS=m
-# CONFIG_ARCNET_COM20020_CS is not set
-CONFIG_PCMCIA_IBMTR=m
-CONFIG_PCMCIA_XIRCOM=m
-CONFIG_PCMCIA_XIRTULIP=m
-CONFIG_NET_PCMCIA_RADIO=y
-CONFIG_PCMCIA_RAYCS=m
-CONFIG_PCMCIA_NETWAVE=m
-CONFIG_PCMCIA_WAVELAN=m
-CONFIG_PCMCIA_WVLAN=m
-CONFIG_AIRONET4500_CS=m
-
-#
-# ATM drivers
-#
-CONFIG_ATM_TCP=m
-CONFIG_ATM_LANAI=m
-CONFIG_ATM_ENI=m
-# CONFIG_ATM_ENI_DEBUG is not set
-# CONFIG_ATM_ENI_TUNE_BURST is not set
-CONFIG_ATM_FIRESTREAM=m
-CONFIG_ATM_ZATM=m
-# CONFIG_ATM_ZATM_DEBUG is not set
-CONFIG_ATM_ZATM_EXACT_TS=y
-CONFIG_ATM_NICSTAR=m
-CONFIG_ATM_NICSTAR_USE_SUNI=y
-CONFIG_ATM_NICSTAR_USE_IDT77105=y
-CONFIG_ATM_IDT77252=m
-# CONFIG_ATM_IDT77252_DEBUG is not set
-# CONFIG_ATM_IDT77252_RCV_ALL is not set
-CONFIG_ATM_IDT77252_USE_SUNI=y
-CONFIG_ATM_AMBASSADOR=m
-# CONFIG_ATM_AMBASSADOR_DEBUG is not set
-CONFIG_ATM_HORIZON=m
-# CONFIG_ATM_HORIZON_DEBUG is not set
-CONFIG_ATM_IA=m
-# CONFIG_ATM_IA_DEBUG is not set
-CONFIG_ATM_FORE200E_MAYBE=m
-CONFIG_ATM_FORE200E_PCA=y
-CONFIG_ATM_FORE200E_PCA_DEFAULT_FW=y
-CONFIG_ATM_FORE200E_TX_RETRY=16
-CONFIG_ATM_FORE200E_DEBUG=0
-CONFIG_ATM_FORE200E=m
-
-#
-# Amateur Radio support
-#
-CONFIG_HAMRADIO=y
-CONFIG_AX25=m
-# CONFIG_AX25_DAMA_SLAVE is not set
-CONFIG_NETROM=m
-CONFIG_ROSE=m
-
-#
-# AX.25 network device drivers
-#
-# CONFIG_MKISS is not set
-# CONFIG_6PACK is not set
-# CONFIG_BPQETHER is not set
-# CONFIG_DMASCC is not set
-# CONFIG_SCC is not set
-# CONFIG_BAYCOM_SER_FDX is not set
-# CONFIG_BAYCOM_SER_HDX is not set
-# CONFIG_BAYCOM_PAR is not set
-# CONFIG_BAYCOM_EPP is not set
-CONFIG_SOUNDMODEM=m
-CONFIG_SOUNDMODEM_SBC=y
-CONFIG_SOUNDMODEM_WSS=y
-CONFIG_SOUNDMODEM_AFSK1200=y
-CONFIG_SOUNDMODEM_AFSK2400_7=y
-CONFIG_SOUNDMODEM_AFSK2400_8=y
-CONFIG_SOUNDMODEM_AFSK2666=y
-CONFIG_SOUNDMODEM_HAPN4800=y
-CONFIG_SOUNDMODEM_PSK4800=y
-CONFIG_SOUNDMODEM_FSK9600=y
-# CONFIG_YAM is not set
-
-#
-# IrDA (infrared) support
-#
-CONFIG_IRDA=m
-CONFIG_IRLAN=m
-CONFIG_IRNET=m
-CONFIG_IRCOMM=m
-CONFIG_IRDA_ULTRA=y
-CONFIG_IRDA_CACHE_LAST_LSAP=y
-CONFIG_IRDA_FAST_RR=y
-# CONFIG_IRDA_DEBUG is not set
-
-#
-# Infrared-port device drivers
-#
-CONFIG_IRTTY_SIR=m
-CONFIG_IRPORT_SIR=m
-CONFIG_DONGLE=y
-CONFIG_ESI_DONGLE=m
-CONFIG_ACTISYS_DONGLE=m
-CONFIG_TEKRAM_DONGLE=m
-CONFIG_GIRBIL_DONGLE=m
-CONFIG_LITELINK_DONGLE=m
-CONFIG_MCP2120_DONGLE=m
-CONFIG_OLD_BELKIN_DONGLE=m
-CONFIG_ACT200L_DONGLE=m
-CONFIG_MA600_DONGLE=m
-CONFIG_USB_IRDA=m
-CONFIG_NSC_FIR=m
-CONFIG_WINBOND_FIR=m
-CONFIG_TOSHIBA_OLD=m
-CONFIG_TOSHIBA_FIR=m
-CONFIG_SMC_IRCC_FIR=m
-CONFIG_ALI_FIR=m
-CONFIG_VLSI_FIR=m
-
-#
-# ISDN subsystem
-#
-CONFIG_ISDN=m
-CONFIG_ISDN_BOOL=y
-CONFIG_ISDN_PPP=y
-CONFIG_ISDN_PPP_VJ=y
-CONFIG_ISDN_MPP=y
-CONFIG_ISDN_PPP_BSDCOMP=m
-CONFIG_ISDN_AUDIO=y
-CONFIG_ISDN_TTY_FAX=y
-
-#
-# ISDN feature submodules
-#
-CONFIG_ISDN_DRV_LOOP=m
-# CONFIG_ISDN_DIVERSION is not set
-
-#
-# Passive ISDN cards
-#
-CONFIG_ISDN_DRV_HISAX=m
-CONFIG_ISDN_HISAX=y
-CONFIG_HISAX_EURO=y
-CONFIG_DE_AOC=y
-# CONFIG_HISAX_NO_SENDCOMPLETE is not set
-# CONFIG_HISAX_NO_LLC is not set
-# CONFIG_HISAX_NO_KEYPAD is not set
-CONFIG_HISAX_1TR6=y
-CONFIG_HISAX_NI1=y
-CONFIG_HISAX_MAX_CARDS=8
-CONFIG_HISAX_16_0=y
-CONFIG_HISAX_16_3=y
-CONFIG_HISAX_AVM_A1=y
-CONFIG_HISAX_IX1MICROR2=y
-CONFIG_HISAX_ASUSCOM=y
-CONFIG_HISAX_TELEINT=y
-CONFIG_HISAX_HFCS=y
-CONFIG_HISAX_SPORTSTER=y
-CONFIG_HISAX_MIC=y
-CONFIG_HISAX_ISURF=y
-CONFIG_HISAX_HSTSAPHIR=y
-CONFIG_HISAX_TELESPCI=y
-CONFIG_HISAX_S0BOX=y
-CONFIG_HISAX_FRITZPCI=y
-CONFIG_HISAX_AVM_A1_PCMCIA=y
-CONFIG_HISAX_ELSA=y
-CONFIG_HISAX_DIEHLDIVA=y
-CONFIG_HISAX_SEDLBAUER=y
-CONFIG_HISAX_NETJET=y
-CONFIG_HISAX_NETJET_U=y
-CONFIG_HISAX_NICCY=y
-CONFIG_HISAX_BKM_A4T=y
-CONFIG_HISAX_SCT_QUADRO=y
-CONFIG_HISAX_GAZEL=y
-CONFIG_HISAX_HFC_PCI=y
-CONFIG_HISAX_W6692=y
-CONFIG_HISAX_HFC_SX=y
-CONFIG_HISAX_ENTERNOW_PCI=y
-CONFIG_HISAX_DEBUG=y
-CONFIG_HISAX_SEDLBAUER_CS=m
-CONFIG_HISAX_ELSA_CS=m
-CONFIG_HISAX_AVM_A1_CS=m
-CONFIG_HISAX_ST5481=m
-CONFIG_HISAX_FRITZ_PCIPNP=m
-CONFIG_USB_AUERISDN=m
-
-#
-# Active ISDN cards
-#
-CONFIG_ISDN_DRV_ICN=m
-CONFIG_ISDN_DRV_PCBIT=m
-# CONFIG_ISDN_DRV_SC is not set
-# CONFIG_ISDN_DRV_ACT2000 is not set
-CONFIG_ISDN_DRV_EICON=y
-CONFIG_ISDN_DRV_EICON_DIVAS=m
-# CONFIG_ISDN_DRV_EICON_OLD is not set
-CONFIG_ISDN_DRV_TPAM=m
-CONFIG_ISDN_CAPI=m
-CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
-CONFIG_ISDN_CAPI_MIDDLEWARE=y
-CONFIG_ISDN_CAPI_CAPI20=m
-CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
-CONFIG_ISDN_CAPI_CAPIFS=m
-CONFIG_ISDN_CAPI_CAPIDRV=m
-CONFIG_ISDN_DRV_AVMB1_B1ISA=m
-CONFIG_ISDN_DRV_AVMB1_B1PCI=m
-CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
-CONFIG_ISDN_DRV_AVMB1_T1ISA=m
-CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
-CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
-CONFIG_ISDN_DRV_AVMB1_T1PCI=m
-CONFIG_ISDN_DRV_AVMB1_C4=m
-CONFIG_HYSDN=m
-CONFIG_HYSDN_CAPI=y
-CONFIG_KALLSYMS=y
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Input core support
-#
-CONFIG_INPUT=m
-CONFIG_INPUT_KEYBDEV=m
-CONFIG_INPUT_MOUSEDEV=m
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-CONFIG_INPUT_JOYDEV=m
-CONFIG_INPUT_EVDEV=m
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_ECC=m
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-CONFIG_SERIAL_EXTENDED=y
-CONFIG_SERIAL_MANY_PORTS=y
-CONFIG_SERIAL_SHARE_IRQ=y
-# CONFIG_SERIAL_DETECT_IRQ is not set
-CONFIG_SERIAL_MULTIPORT=y
-# CONFIG_HUB6 is not set
-CONFIG_SERIAL_NONSTANDARD=y
-CONFIG_COMPUTONE=m
-CONFIG_ROCKETPORT=m
-CONFIG_CYCLADES=m
-# CONFIG_CYZ_INTR is not set
-CONFIG_DIGIEPCA=m
-CONFIG_ESPSERIAL=m
-CONFIG_MOXA_INTELLIO=m
-CONFIG_MOXA_SMARTIO=m
-CONFIG_ISI=m
-CONFIG_SYNCLINK=m
-# CONFIG_SYNCLINKMP is not set
-CONFIG_N_HDLC=m
-CONFIG_RISCOM8=m
-CONFIG_SPECIALIX=m
-CONFIG_SPECIALIX_RTSCTS=y
-CONFIG_SX=m
-# CONFIG_RIO is not set
-CONFIG_STALDRV=y
-CONFIG_STALLION=m
-CONFIG_ISTALLION=m
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=2048
-CONFIG_PRINTER=m
-CONFIG_LP_CONSOLE=y
-CONFIG_PPDEV=m
-CONFIG_TIPAR=m
-
-#
-# I2C support
-#
-CONFIG_I2C=m
-CONFIG_I2C_ALGOBIT=m
-CONFIG_I2C_PHILIPSPAR=m
-CONFIG_I2C_ELV=m
-CONFIG_I2C_VELLEMAN=m
-# CONFIG_SCx200_I2C is not set
-# CONFIG_SCx200_ACB is not set
-CONFIG_I2C_ALGOPCF=m
-CONFIG_I2C_ELEKTOR=m
-CONFIG_I2C_MAINBOARD=y
-CONFIG_I2C_ALI1535=m
-CONFIG_I2C_ALI15X3=m
-CONFIG_I2C_HYDRA=m
-CONFIG_I2C_AMD756=m
-# CONFIG_I2C_TSUNAMI is not set
-CONFIG_I2C_I801=m
-# CONFIG_I2C_I810 is not set
-CONFIG_I2C_PIIX4=m
-CONFIG_I2C_SIS5595=m
-CONFIG_I2C_VIA=m
-CONFIG_I2C_VIAPRO=m
-CONFIG_I2C_VOODOO3=m
-CONFIG_I2C_ISA=m
-CONFIG_I2C_CHARDEV=m
-CONFIG_I2C_PROC=m
-
-#
-# Hardware sensors support
-#
-CONFIG_SENSORS=y
-CONFIG_SENSORS_ADM1021=m
-CONFIG_SENSORS_ADM1024=m
-CONFIG_SENSORS_ADM1025=m
-CONFIG_SENSORS_ADM9240=m
-CONFIG_SENSORS_DS1621=m
-CONFIG_SENSORS_FSCPOS=m
-CONFIG_SENSORS_FSCSCY=m
-CONFIG_SENSORS_GL518SM=m
-CONFIG_SENSORS_GL520SM=m
-CONFIG_SENSORS_MAXILIFE=m
-CONFIG_SENSORS_IT87=m
-CONFIG_SENSORS_MTP008=m
-CONFIG_SENSORS_LM75=m
-CONFIG_SENSORS_LM78=m
-CONFIG_SENSORS_LM80=m
-CONFIG_SENSORS_LM87=m
-CONFIG_SENSORS_LM92=m
-CONFIG_SENSORS_SIS5595=m
-CONFIG_SENSORS_SMSC47M1=m
-CONFIG_SENSORS_THMC50=m
-CONFIG_SENSORS_VIA686A=m
-CONFIG_SENSORS_VT1211=m
-CONFIG_SENSORS_VT8231=m
-CONFIG_SENSORS_W83781D=m
-CONFIG_SENSORS_OTHER=y
-CONFIG_SENSORS_BT869=m
-CONFIG_SENSORS_DDCMON=m
-CONFIG_SENSORS_EEPROM=m
-CONFIG_SENSORS_MATORB=m
-CONFIG_SENSORS_PCF8574=m
-CONFIG_SENSORS_PCF8591=m
-
-#
-# Mice
-#
-CONFIG_BUSMOUSE=m
-CONFIG_ATIXL_BUSMOUSE=m
-CONFIG_LOGIBUSMOUSE=m
-CONFIG_MS_BUSMOUSE=m
-CONFIG_MOUSE=y
-CONFIG_PSMOUSE=y
-CONFIG_82C710_MOUSE=m
-CONFIG_PC110_PAD=m
-CONFIG_MK712_MOUSE=m
-
-#
-# Joysticks
-#
-CONFIG_INPUT_GAMEPORT=m
-CONFIG_INPUT_NS558=m
-CONFIG_INPUT_LIGHTNING=m
-CONFIG_INPUT_PCIGAME=m
-CONFIG_INPUT_CS461X=m
-CONFIG_INPUT_EMU10K1=m
-CONFIG_INPUT_SERIO=m
-CONFIG_INPUT_SERPORT=m
-CONFIG_INPUT_ANALOG=m
-CONFIG_INPUT_A3D=m
-CONFIG_INPUT_ADI=m
-CONFIG_INPUT_COBRA=m
-CONFIG_INPUT_GF2K=m
-CONFIG_INPUT_GRIP=m
-CONFIG_INPUT_INTERACT=m
-CONFIG_INPUT_TMDC=m
-CONFIG_INPUT_SIDEWINDER=m
-CONFIG_INPUT_IFORCE_USB=m
-CONFIG_INPUT_IFORCE_232=m
-CONFIG_INPUT_WARRIOR=m
-CONFIG_INPUT_MAGELLAN=m
-CONFIG_INPUT_SPACEORB=m
-CONFIG_INPUT_SPACEBALL=m
-CONFIG_INPUT_STINGER=m
-CONFIG_INPUT_DB9=m
-CONFIG_INPUT_GAMECON=m
-CONFIG_INPUT_TURBOGRAFX=m
-# CONFIG_QIC02_TAPE is not set
-CONFIG_IPMI_HANDLER=m
-# CONFIG_IPMI_PANIC_EVENT is not set
-CONFIG_IPMI_DEVICE_INTERFACE=m
-CONFIG_IPMI_KCS=m
-CONFIG_IPMI_WATCHDOG=m
-
-#
-# Watchdog Cards
-#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-CONFIG_ACQUIRE_WDT=m
-CONFIG_ADVANTECH_WDT=m
-CONFIG_ALIM7101_WDT=m
-CONFIG_SC520_WDT=m
-CONFIG_PCWATCHDOG=m
-CONFIG_EUROTECH_WDT=m
-CONFIG_IB700_WDT=m
-CONFIG_WAFER_WDT=m
-CONFIG_I810_TCO=m
-# CONFIG_MIXCOMWD is not set
-# CONFIG_60XX_WDT is not set
-CONFIG_SC1200_WDT=m
-# CONFIG_SCx200_WDT is not set
-CONFIG_SOFT_WATCHDOG=m
-CONFIG_W83877F_WDT=m
-CONFIG_WDT=m
-CONFIG_WDTPCI=m
-# CONFIG_WDT_501 is not set
-CONFIG_MACHZ_WDT=m
-CONFIG_AMD7XX_TCO=m
-# CONFIG_SCx200_GPIO is not set
-CONFIG_AMD_RNG=m
-CONFIG_INTEL_RNG=m
-CONFIG_AMD_PM768=m
-CONFIG_NVRAM=m
-CONFIG_RTC=y
-CONFIG_DTLK=m
-CONFIG_R3964=m
-# CONFIG_APPLICOM is not set
-CONFIG_SONYPI=m
-
-#
-# Ftape, the floppy tape device driver
-#
-CONFIG_FTAPE=m
-CONFIG_ZFTAPE=m
-CONFIG_ZFT_DFLT_BLK_SZ=10240
-CONFIG_ZFT_COMPRESSOR=m
-CONFIG_FT_NR_BUFFERS=3
-# CONFIG_FT_PROC_FS is not set
-CONFIG_FT_NORMAL_DEBUG=y
-# CONFIG_FT_FULL_DEBUG is not set
-# CONFIG_FT_NO_TRACE is not set
-# CONFIG_FT_NO_TRACE_AT_ALL is not set
-CONFIG_FT_STD_FDC=y
-# CONFIG_FT_MACH2 is not set
-# CONFIG_FT_PROBE_FC10 is not set
-# CONFIG_FT_ALT_FDC is not set
-CONFIG_FT_FDC_THR=8
-CONFIG_FT_FDC_MAX_RATE=2000
-CONFIG_FT_ALPHA_CLOCK=0
-CONFIG_AGP=m
-CONFIG_AGP_INTEL=y
-CONFIG_AGP_I810=y
-CONFIG_AGP_VIA=y
-CONFIG_AGP_AMD=y
-CONFIG_AGP_AMD_8151=y
-CONFIG_AGP_SIS=y
-CONFIG_AGP_ALI=y
-CONFIG_AGP_SWORKS=y
-CONFIG_DRM=y
-# CONFIG_DRM_OLD is not set
-CONFIG_DRM_NEW=y
-CONFIG_DRM_TDFX=m
-CONFIG_DRM_R128=m
-CONFIG_DRM_RADEON=m
-CONFIG_DRM_I810=m
-# CONFIG_DRM_I810_XFREE_41 is not set
-CONFIG_DRM_I830=m
-CONFIG_DRM_MGA=m
-# CONFIG_DRM_SIS is not set
-
-#
-# PCMCIA character devices
-#
-CONFIG_PCMCIA_SERIAL_CS=m
-CONFIG_SYNCLINK_CS=m
-CONFIG_MWAVE=m
-CONFIG_BATTERY_GERICOM=m
-
-#
-# Multimedia devices
-#
-CONFIG_VIDEO_DEV=m
-
-#
-# Video For Linux
-#
-CONFIG_VIDEO_PROC_FS=y
-CONFIG_I2C_PARPORT=m
-CONFIG_VIDEO_BT848=m
-CONFIG_VIDEO_PMS=m
-CONFIG_VIDEO_BWQCAM=m
-CONFIG_VIDEO_CQCAM=m
-CONFIG_VIDEO_W9966=m
-CONFIG_VIDEO_CPIA=m
-CONFIG_VIDEO_CPIA_PP=m
-CONFIG_VIDEO_CPIA_USB=m
-CONFIG_VIDEO_SAA5249=m
-CONFIG_TUNER_3036=m
-CONFIG_VIDEO_STRADIS=m
-CONFIG_VIDEO_ZORAN=m
-CONFIG_VIDEO_ZORAN_BUZ=m
-CONFIG_VIDEO_ZORAN_DC10=m
-CONFIG_VIDEO_ZORAN_LML33=m
-CONFIG_VIDEO_ZR36120=m
-CONFIG_VIDEO_MEYE=m
-
-#
-# Radio Adapters
-#
-CONFIG_RADIO_CADET=m
-CONFIG_RADIO_RTRACK=m
-CONFIG_RADIO_RTRACK2=m
-CONFIG_RADIO_AZTECH=m
-CONFIG_RADIO_GEMTEK=m
-CONFIG_RADIO_GEMTEK_PCI=m
-CONFIG_RADIO_MAXIRADIO=m
-CONFIG_RADIO_MAESTRO=m
-CONFIG_RADIO_MIROPCM20=m
-CONFIG_RADIO_MIROPCM20_RDS=m
-CONFIG_RADIO_SF16FMI=m
-CONFIG_RADIO_SF16FMR2=m
-CONFIG_RADIO_TERRATEC=m
-CONFIG_RADIO_TRUST=m
-CONFIG_RADIO_TYPHOON=m
-CONFIG_RADIO_TYPHOON_PROC_FS=y
-CONFIG_RADIO_ZOLTRIX=m
-
-#
-# Crypto Hardware support
-#
-CONFIG_CRYPTO=m
-CONFIG_CRYPTO_BROADCOM=m
-
-#
-# File systems
-#
-CONFIG_QUOTA=y
-# CONFIG_QFMT_V1 is not set
-CONFIG_QFMT_V2=y
-# CONFIG_QIFACE_COMPAT is not set
-CONFIG_AUTOFS_FS=m
-CONFIG_AUTOFS4_FS=m
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-CONFIG_REISERFS_PROC_INFO=y
-# CONFIG_ADFS_FS is not set
-CONFIG_AFS_FS=m
-# CONFIG_ADFS_FS_RW is not set
-# CONFIG_AFFS_FS is not set
-CONFIG_HFS_FS=m
-CONFIG_BEFS_FS=m
-# CONFIG_BEFS_DEBUG is not set
-CONFIG_BFS_FS=m
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-CONFIG_EXT3_FS_XATTR_SHARING=y
-CONFIG_EXT3_FS_XATTR_USER=y
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_UMSDOS_FS=m
-CONFIG_VFAT_FS=m
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-CONFIG_CRAMFS=m
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_JFS_FS=m
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
-CONFIG_MINIX_FS=m
-CONFIG_VXFS_FS=m
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_RW is not set
-# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-CONFIG_ROMFS_FS=m
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_XATTR_SHARING=y
-CONFIG_EXT2_FS_XATTR_USER=y
-CONFIG_SYSV_FS=m
-CONFIG_UDF_FS=m
-CONFIG_UDF_RW=y
-CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
-
-#
-# Network File Systems
-#
-CONFIG_CODA_FS=m
-CONFIG_INTERMEZZO_FS=m
-CONFIG_NFS_FS=m
-CONFIG_NFS_V3=y
-# CONFIG_ROOT_NFS is not set
-CONFIG_NFSD=m
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_TCP is not set
-CONFIG_SUNRPC=m
-CONFIG_LOCKD=m
-CONFIG_LOCKD_V4=y
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
-CONFIG_NCP_FS=m
-CONFIG_NCPFS_PACKET_SIGNING=y
-CONFIG_NCPFS_IOCTL_LOCKING=y
-CONFIG_NCPFS_STRONG=y
-CONFIG_NCPFS_NFS_NS=y
-CONFIG_NCPFS_OS2_NS=y
-CONFIG_NCPFS_SMALLDOS=y
-CONFIG_NCPFS_NLS=y
-CONFIG_NCPFS_EXTRAS=y
-CONFIG_ZISOFS_FS=y
-CONFIG_FS_MBCACHE=y
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-CONFIG_OSF_PARTITION=y
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
-CONFIG_BSD_DISKLABEL=y
-CONFIG_MINIX_SUBPARTITION=y
-CONFIG_SOLARIS_X86_PARTITION=y
-CONFIG_UNIXWARE_DISKLABEL=y
-# CONFIG_LDM_PARTITION is not set
-CONFIG_SGI_PARTITION=y
-# CONFIG_ULTRIX_PARTITION is not set
-CONFIG_SUN_PARTITION=y
-# CONFIG_EFI_PARTITION is not set
-CONFIG_SMB_NLS=y
-CONFIG_NLS=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=m
-
-#
-# Console drivers
-#
-CONFIG_VGA_CONSOLE=y
-CONFIG_VIDEO_SELECT=y
-# CONFIG_VIDEO_IGNORE_BAD_MODE is not set
-CONFIG_MDA_CONSOLE=m
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FB_RIVA=m
-CONFIG_FB_CLGEN=m
-CONFIG_FB_PM2=m
-# CONFIG_FB_PM2_FIFO_DISCONNECT is not set
-CONFIG_FB_PM2_PCI=y
-CONFIG_FB_PM3=m
-# CONFIG_FB_CYBER2000 is not set
-CONFIG_FB_VESA=y
-CONFIG_FB_VGA16=m
-CONFIG_FB_HGA=m
-CONFIG_VIDEO_SELECT=y
-CONFIG_FB_MATROX=m
-CONFIG_FB_MATROX_MILLENIUM=y
-CONFIG_FB_MATROX_MYSTIQUE=y
-# CONFIG_FB_MATROX_G450 is not set
-CONFIG_FB_MATROX_G100A=y
-CONFIG_FB_MATROX_G100=y
-CONFIG_FB_MATROX_I2C=m
-CONFIG_FB_MATROX_MAVEN=m
-# CONFIG_FB_MATROX_PROC is not set
-CONFIG_FB_MATROX_MULTIHEAD=y
-CONFIG_FB_ATY=m
-CONFIG_FB_ATY_GX=y
-CONFIG_FB_ATY_CT=y
-CONFIG_FB_ATY_CT_VAIO_LCD=y
-CONFIG_FB_RADEON=m
-CONFIG_FB_ATY128=m
-CONFIG_FB_SIS=m
-CONFIG_FB_SIS_300=y
-CONFIG_FB_SIS_315=y
-CONFIG_FB_NEOMAGIC=m
-CONFIG_FB_3DFX=m
-CONFIG_FB_VOODOO1=m
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-# CONFIG_FBCON_ADVANCED is not set
-CONFIG_FBCON_MFB=m
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-CONFIG_FBCON_CFB24=y
-CONFIG_FBCON_CFB32=y
-CONFIG_FBCON_VGA_PLANES=m
-CONFIG_FBCON_HGA=m
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-# CONFIG_FBCON_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Sound
-#
-CONFIG_SOUND=m
-CONFIG_SOUND_ALI5455=m
-CONFIG_SOUND_BT878=m
-CONFIG_SOUND_CMPCI=m
-CONFIG_SOUND_CMPCI_FM=y
-CONFIG_SOUND_CMPCI_FMIO=388
-CONFIG_SOUND_CMPCI_FMIO=388
-CONFIG_SOUND_CMPCI_MIDI=y
-CONFIG_SOUND_CMPCI_MPUIO=330
-CONFIG_SOUND_CMPCI_JOYSTICK=y
-CONFIG_SOUND_CMPCI_CM8738=y
-# CONFIG_SOUND_CMPCI_SPDIFINVERSE is not set
-CONFIG_SOUND_CMPCI_SPDIFLOOP=y
-CONFIG_SOUND_CMPCI_SPEAKERS=2
-CONFIG_SOUND_EMU10K1=m
-CONFIG_MIDI_EMU10K1=y
-CONFIG_SOUND_AUDIGY=m
-CONFIG_SOUND_FUSION=m
-CONFIG_SOUND_CS4281=m
-CONFIG_SOUND_ES1370=m
-CONFIG_SOUND_ES1371=m
-CONFIG_SOUND_ESSSOLO1=m
-CONFIG_SOUND_MAESTRO=m
-CONFIG_SOUND_MAESTRO3=m
-CONFIG_SOUND_FORTE=m
-CONFIG_SOUND_ICH=m
-CONFIG_SOUND_RME96XX=m
-CONFIG_SOUND_SONICVIBES=m
-CONFIG_SOUND_TRIDENT=m
-CONFIG_SOUND_MSNDCLAS=m
-# CONFIG_MSNDCLAS_HAVE_BOOT is not set
-CONFIG_MSNDCLAS_INIT_FILE="/etc/sound/msndinit.bin"
-CONFIG_MSNDCLAS_PERM_FILE="/etc/sound/msndperm.bin"
-CONFIG_SOUND_MSNDPIN=m
-# CONFIG_MSNDPIN_HAVE_BOOT is not set
-CONFIG_MSNDPIN_INIT_FILE="/etc/sound/pndspini.bin"
-CONFIG_MSNDPIN_PERM_FILE="/etc/sound/pndsperm.bin"
-CONFIG_SOUND_VIA82CXXX=m
-CONFIG_MIDI_VIA82CXXX=y
-CONFIG_SOUND_OSS=m
-# CONFIG_SOUND_TRACEINIT is not set
-CONFIG_SOUND_DMAP=y
-CONFIG_SOUND_AD1816=m
-CONFIG_SOUND_AD1889=m
-CONFIG_SOUND_SGALAXY=m
-CONFIG_SOUND_ADLIB=m
-CONFIG_SOUND_ACI_MIXER=m
-CONFIG_SOUND_CS4232=m
-CONFIG_SOUND_SSCAPE=m
-CONFIG_SOUND_GUS=m
-CONFIG_SOUND_GUS16=y
-CONFIG_SOUND_GUSMAX=y
-CONFIG_SOUND_VMIDI=m
-CONFIG_SOUND_TRIX=m
-CONFIG_SOUND_MSS=m
-CONFIG_SOUND_MPU401=m
-CONFIG_SOUND_NM256=m
-CONFIG_SOUND_MAD16=m
-CONFIG_MAD16_OLDCARD=y
-CONFIG_SOUND_PAS=m
-# CONFIG_PAS_JOYSTICK is not set
-CONFIG_SOUND_PSS=m
-# CONFIG_PSS_MIXER is not set
-# CONFIG_PSS_HAVE_BOOT is not set
-CONFIG_SOUND_SB=m
-CONFIG_SOUND_AWE32_SYNTH=m
-CONFIG_SOUND_KAHLUA=m
-CONFIG_SOUND_WAVEFRONT=m
-CONFIG_SOUND_MAUI=m
-CONFIG_SOUND_YM3812=m
-CONFIG_SOUND_OPL3SA1=m
-CONFIG_SOUND_OPL3SA2=m
-CONFIG_SOUND_YMFPCI=m
-CONFIG_SOUND_YMFPCI_LEGACY=y
-CONFIG_SOUND_UART6850=m
-CONFIG_SOUND_AEDSP16=m
-CONFIG_SC6600=y
-CONFIG_SC6600_JOY=y
-CONFIG_SC6600_CDROM=4
-CONFIG_SC6600_CDROMBASE=0
-CONFIG_AEDSP16_SBPRO=y
-CONFIG_AEDSP16_MPU401=y
-CONFIG_SOUND_TVMIXER=m
-
-#
-# USB support
-#
-CONFIG_USB=m
-# CONFIG_USB_DEBUG is not set
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
-CONFIG_USB_EHCI_HCD=m
-CONFIG_USB_UHCI=m
-CONFIG_USB_UHCI_ALT=m
-CONFIG_USB_OHCI=m
-CONFIG_USB_AUDIO=m
-# CONFIG_USB_EMI26 is not set
-CONFIG_USB_MIDI=m
-CONFIG_USB_STORAGE=m
-# CONFIG_USB_STORAGE_DEBUG is not set
-CONFIG_USB_STORAGE_DATAFAB=y
-CONFIG_USB_STORAGE_FREECOM=y
-CONFIG_USB_STORAGE_ISD200=y
-CONFIG_USB_STORAGE_DPCM=y
-CONFIG_USB_STORAGE_HP8200e=y
-CONFIG_USB_STORAGE_SDDR09=y
-CONFIG_USB_STORAGE_SDDR55=y
-CONFIG_USB_STORAGE_JUMPSHOT=y
-CONFIG_USB_ACM=m
-CONFIG_USB_PRINTER=m
-CONFIG_USB_HID=m
-CONFIG_USB_HIDINPUT=y
-CONFIG_USB_HIDDEV=y
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
-CONFIG_USB_AIPTEK=m
-CONFIG_USB_WACOM=m
-CONFIG_USB_KBTAB=m
-CONFIG_USB_POWERMATE=m
-# CONFIG_USB_DC2XX is not set
-CONFIG_USB_MDC800=m
-CONFIG_USB_SCANNER=m
-CONFIG_USB_MICROTEK=m
-CONFIG_USB_HPUSBSCSI=m
-CONFIG_USB_IBMCAM=m
-CONFIG_USB_KONICAWC=m
-CONFIG_USB_OV511=m
-CONFIG_USB_PWC=m
-CONFIG_USB_SE401=m
-CONFIG_USB_STV680=m
-CONFIG_USB_VICAM=m
-CONFIG_USB_DSBR=m
-CONFIG_USB_DABUSB=m
-CONFIG_USB_PEGASUS=m
-CONFIG_USB_RTL8150=m
-CONFIG_USB_KAWETH=m
-CONFIG_USB_CATC=m
-CONFIG_USB_CDCETHER=m
-CONFIG_USB_USBNET=m
-CONFIG_USB_USS720=m
-
-#
-# USB Serial Converter support
-#
-CONFIG_USB_SERIAL=m
-# CONFIG_USB_SERIAL_DEBUG is not set
-CONFIG_USB_SERIAL_GENERIC=y
-CONFIG_USB_SERIAL_BELKIN=m
-CONFIG_USB_SERIAL_WHITEHEAT=m
-CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
-CONFIG_USB_SERIAL_EMPEG=m
-CONFIG_USB_SERIAL_FTDI_SIO=m
-CONFIG_USB_SERIAL_VISOR=m
-CONFIG_USB_SERIAL_IPAQ=m
-CONFIG_USB_SERIAL_IR=m
-CONFIG_USB_SERIAL_EDGEPORT=m
-CONFIG_USB_SERIAL_EDGEPORT_TI=m
-CONFIG_USB_SERIAL_KEYSPAN_PDA=m
-CONFIG_USB_SERIAL_KEYSPAN=m
-# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
-CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
-# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
-CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
-CONFIG_USB_SERIAL_KEYSPAN_MPR=y
-CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
-CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
-CONFIG_USB_SERIAL_MCT_U232=m
-CONFIG_USB_SERIAL_KLSI=m
-CONFIG_USB_SERIAL_KOBIL_SCT=m
-CONFIG_USB_SERIAL_PL2303=m
-CONFIG_USB_SERIAL_CYBERJACK=m
-CONFIG_USB_SERIAL_XIRCOM=m
-CONFIG_USB_SERIAL_OMNINET=m
-CONFIG_USB_RIO500=m
-CONFIG_USB_AUERSWALD=m
-CONFIG_USB_TIGL=m
-CONFIG_USB_BRLVGER=m
-CONFIG_USB_LCD=m
-
-#
-# Additional device driver support
-#
-CONFIG_NET_BROADCOM=m
-CONFIG_CIPE=m
-CONFIG_CRYPTO_AEP=m
-CONFIG_MEGARAC=m
-CONFIG_FC_QLA2200=m
-CONFIG_FC_QLA2300=m
-CONFIG_SCSI_ISCSI=m
-
-#
-# Bluetooth support
-#
-CONFIG_BLUEZ=m
-CONFIG_BLUEZ_L2CAP=m
-CONFIG_BLUEZ_SCO=m
-CONFIG_BLUEZ_RFCOMM=m
-CONFIG_BLUEZ_RFCOMM_TTY=y
-CONFIG_BLUEZ_BNEP=m
-CONFIG_BLUEZ_BNEP_MC_FILTER=y
-CONFIG_BLUEZ_BNEP_PROTO_FILTER=y
-
-#
-# Bluetooth device drivers
-#
-CONFIG_BLUEZ_HCIUSB=m
-CONFIG_BLUEZ_USB_SCO=y
-CONFIG_BLUEZ_USB_ZERO_PACKET=y
-CONFIG_BLUEZ_HCIUART=m
-CONFIG_BLUEZ_HCIUART_H4=y
-CONFIG_BLUEZ_HCIUART_BCSP=y
-CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y
-CONFIG_BLUEZ_HCIDTL1=m
-CONFIG_BLUEZ_HCIBT3C=m
-CONFIG_BLUEZ_HCIBLUECARD=m
-CONFIG_BLUEZ_HCIBTUART=m
-CONFIG_BLUEZ_HCIVHCI=m
-
-#
-# Profiling support
-#
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=m
-
-#
-# Kernel hacking
-#
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_STACKOVERFLOW is not set
-# CONFIG_DEBUG_HIGHMEM is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_IOVIRT is not set
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_DEBUG_SPINLOCK is not set
-CONFIG_FRAME_POINTER=y
-# CONFIG_MCL_COREDUMP is not set
-
-#
-# Library routines
-#
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=m
+++ /dev/null
-#
-# Automatically generated by make menuconfig: don't edit
-#
-CONFIG_X86_64=y
-CONFIG_X86=y
-# CONFIG_ISA is not set
-# CONFIG_SBUS is not set
-CONFIG_UID16=y
-CONFIG_X86_CMPXCHG=y
-CONFIG_EARLY_PRINTK=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
-# Processor type and features
-#
-CONFIG_MK8=y
-# CONFIG_GENERIC_CPU is not set
-CONFIG_X86_L1_CACHE_BYTES=64
-CONFIG_X86_L1_CACHE_SHIFT=6
-CONFIG_X86_TSC=y
-CONFIG_X86_GOOD_APIC=y
-
-#
-# CPU Frequency scaling
-#
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_TABLE=y
-CONFIG_CPU_FREQ_PROC_INTF=y
-CONFIG_CPU_FREQ_GOV_USERSPACE=y
-CONFIG_CPU_FREQ_24_API=y
-CONFIG_X86_POWERNOW_K8=m
-# CONFIG_X86_POWERNOW_K8_DBG is not set
-CONFIG_X86_MSR=m
-CONFIG_X86_CPUID=m
-# CONFIG_MATH_EMULATION is not set
-# CONFIG_MCA is not set
-# CONFIG_EISA is not set
-CONFIG_X86_IO_APIC=y
-CONFIG_X86_LOCAL_APIC=y
-CONFIG_MTRR=y
-# CONFIG_SMP is not set
-CONFIG_HPET_TIMER=y
-CONFIG_GART_IOMMU=y
-CONFIG_X86_UP_IOAPIC=y
-CONFIG_MCE=y
-# CONFIG_K8_NUMA is not set
-
-#
-# General setup
-#
-# CONFIG_DESKTOP is not set
-CONFIG_NET=y
-CONFIG_EVLOG=y
-CONFIG_EVLOG_BUFSIZE=128
-CONFIG_EVLOG_FWPRINTK=y
-# CONFIG_EVLOG_PRINTKWLOC is not set
-CONFIG_PCI=y
-CONFIG_PCI_DIRECT=y
-# CONFIG_PCI_NAMES is not set
-CONFIG_HOTPLUG=y
-
-#
-# PCMCIA/CardBus support
-#
-CONFIG_PCMCIA=m
-CONFIG_CARDBUS=y
-CONFIG_TCIC=y
-CONFIG_I82092=y
-CONFIG_I82365=y
-
-#
-# PCI Hotplug Support
-#
-CONFIG_HOTPLUG_PCI=m
-# CONFIG_HOTPLUG_PCI_COMPAQ is not set
-# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
-# CONFIG_HOTPLUG_PCI_IBM is not set
-CONFIG_HOTPLUG_PCI_ACPI=m
-CONFIG_HOTPLUG_PCI_AMD=m
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-CONFIG_MAX_USER_RT_PRIO=100
-CONFIG_MAX_RT_PRIO=0
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=m
-CONFIG_PM=y
-CONFIG_IA32_EMULATION=y
-
-#
-# ACPI Support
-#
-CONFIG_ACPI=y
-# CONFIG_ACPI_HT_ONLY is not set
-CONFIG_ACPI_INITRD=y
-CONFIG_ACPI_BOOT=y
-CONFIG_ACPI_BUS=y
-CONFIG_ACPI_INTERPRETER=y
-CONFIG_ACPI_EC=y
-CONFIG_ACPI_POWER=y
-CONFIG_ACPI_PCI=y
-CONFIG_ACPI_SLEEP=y
-CONFIG_ACPI_SYSTEM=y
-CONFIG_ACPI_AC=m
-CONFIG_ACPI_BATTERY=m
-CONFIG_ACPI_BUTTON=m
-CONFIG_ACPI_FAN=m
-CONFIG_ACPI_PROCESSOR=m
-CONFIG_ACPI_THERMAL=m
-CONFIG_ACPI_ASUS=m
-CONFIG_ACPI_TOSHIBA=m
-# CONFIG_ACPI_DEBUG is not set
-CONFIG_ACPI_RELAXED_AML=y
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=m
-# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=m
-CONFIG_MTD_CONCAT=m
-CONFIG_MTD_REDBOOT_PARTS=m
-CONFIG_MTD_CMDLINE_PARTS=m
-CONFIG_MTD_CHAR=m
-CONFIG_MTD_BLOCK=m
-CONFIG_MTD_BLOCK_RO=m
-CONFIG_FTL=m
-CONFIG_NFTL=m
-# CONFIG_NFTL_RW is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=m
-CONFIG_MTD_JEDECPROBE=m
-CONFIG_MTD_GEN_PROBE=m
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_NOSWAP=y
-# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_GEOMETRY is not set
-CONFIG_MTD_CFI_INTELEXT=m
-CONFIG_MTD_CFI_AMDSTD=m
-CONFIG_MTD_CFI_STAA=m
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-CONFIG_MTD_ABSENT=m
-CONFIG_MTD_OBSOLETE_CHIPS=y
-CONFIG_MTD_AMDSTD=m
-CONFIG_MTD_SHARP=m
-CONFIG_MTD_JEDEC=m
-
-#
-# Mapping drivers for chip access
-#
-CONFIG_MTD_PHYSMAP=m
-CONFIG_MTD_PHYSMAP_START=8000000
-CONFIG_MTD_PHYSMAP_LEN=4000000
-CONFIG_MTD_PHYSMAP_BUSWIDTH=2
-CONFIG_MTD_PNC2000=m
-CONFIG_MTD_SC520CDP=m
-CONFIG_MTD_NETSC520=m
-CONFIG_MTD_SBC_GXX=m
-CONFIG_MTD_ELAN_104NC=m
-CONFIG_MTD_DILNETPC=m
-CONFIG_MTD_DILNETPC_BOOTSIZE=80000
-CONFIG_MTD_MIXMEM=m
-CONFIG_MTD_OCTAGON=m
-CONFIG_MTD_VMAX=m
-CONFIG_MTD_SCx200_DOCFLASH=m
-CONFIG_MTD_L440GX=m
-# CONFIG_MTD_AMD76XROM is not set
-CONFIG_MTD_ICH2ROM=m
-CONFIG_MTD_NETtel=m
-# CONFIG_MTD_SCB2_FLASH is not set
-CONFIG_MTD_PCI=m
-CONFIG_MTD_PCMCIA=m
-
-#
-# Self-contained MTD device drivers
-#
-CONFIG_MTD_PMC551=m
-CONFIG_MTD_PMC551_BUGFIX=y
-# CONFIG_MTD_PMC551_DEBUG is not set
-CONFIG_MTD_SLRAM=m
-CONFIG_MTD_MTDRAM=m
-CONFIG_MTDRAM_TOTAL_SIZE=4096
-CONFIG_MTDRAM_ERASE_SIZE=128
-CONFIG_MTD_BLKMTD=m
-CONFIG_MTD_DOC1000=m
-CONFIG_MTD_DOC2000=m
-CONFIG_MTD_DOC2001=m
-CONFIG_MTD_DOCPROBE=m
-CONFIG_MTD_DOCPROBE_ADVANCED=y
-CONFIG_MTD_DOCPROBE_ADDRESS=0000
-CONFIG_MTD_DOCPROBE_HIGH=y
-CONFIG_MTD_DOCPROBE_55AA=y
-
-#
-# NAND Flash Device Drivers
-#
-CONFIG_MTD_NAND=m
-# CONFIG_MTD_NAND_VERIFY_WRITE is not set
-CONFIG_MTD_NAND_IDS=m
-
-#
-# Parallel port support
-#
-CONFIG_PARPORT=m
-CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_CML1=m
-CONFIG_PARPORT_SERIAL=m
-CONFIG_PARPORT_PC_FIFO=y
-CONFIG_PARPORT_PC_SUPERIO=y
-CONFIG_PARPORT_PC_PCMCIA=m
-# CONFIG_PARPORT_AMIGA is not set
-# CONFIG_PARPORT_MFC3 is not set
-# CONFIG_PARPORT_ATARI is not set
-# CONFIG_PARPORT_GSC is not set
-# CONFIG_PARPORT_SUNBPP is not set
-CONFIG_PARPORT_OTHER=y
-CONFIG_PARPORT_1284=y
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_FD=y
-# CONFIG_BLK_DEV_XD is not set
-CONFIG_PARIDE=m
-CONFIG_PARIDE_PARPORT=m
-CONFIG_PARIDE_PD=m
-CONFIG_PARIDE_PCD=m
-CONFIG_PARIDE_PF=m
-CONFIG_PARIDE_PT=m
-CONFIG_PARIDE_PG=m
-CONFIG_PARIDE_ATEN=m
-CONFIG_PARIDE_BPCK=m
-CONFIG_PARIDE_BPCK6=m
-CONFIG_PARIDE_COMM=m
-CONFIG_PARIDE_DSTR=m
-CONFIG_PARIDE_FIT2=m
-CONFIG_PARIDE_FIT3=m
-CONFIG_PARIDE_EPAT=m
-CONFIG_PARIDE_EPATC8=y
-CONFIG_PARIDE_EPIA=m
-CONFIG_PARIDE_FRIQ=m
-CONFIG_PARIDE_FRPW=m
-CONFIG_PARIDE_KBIC=m
-CONFIG_PARIDE_KTTI=m
-CONFIG_PARIDE_ON20=m
-CONFIG_PARIDE_ON26=m
-CONFIG_BLK_CPQ_DA=m
-CONFIG_BLK_CPQ_CISS_DA=m
-CONFIG_CISS_SCSI_TAPE=y
-CONFIG_BLK_DEV_DAC960=m
-CONFIG_BLK_DEV_UMEM=m
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_CIPHER_TWOFISH=m
-CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=128000
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_BLK_STATS=y
-
-#
-# Multi-device support (RAID and LVM)
-#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=m
-CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_RAID5=m
-CONFIG_MD_MULTIPATH=m
-CONFIG_BLK_DEV_LVM=m
-CONFIG_BLK_DEV_DM=m
-CONFIG_BLK_DEV_DM_MIRROR=m
-
-#
-# Cryptography support (CryptoAPI)
-#
-CONFIG_CRYPTO=y
-CONFIG_CIPHERS=y
-CONFIG_CIPHER_AES=m
-CONFIG_CIPHER_3DES=m
-CONFIG_CIPHER_NULL=m
-CONFIG_CIPHER_DES=m
-CONFIG_DIGESTS=y
-CONFIG_DIGEST_MD5=m
-CONFIG_DIGEST_SHA1=m
-CONFIG_CRYPTODEV=y
-CONFIG_CRYPTOLOOP=m
-CONFIG_CRYPTOLOOP_ATOMIC=y
-# CONFIG_CRYPTOLOOP_IV_HACK is not set
-# CONFIG_CRYPTOLOOP_DEBUG is not set
-
-#
-# Networking options
-#
-CONFIG_PACKET=m
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=m
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_FILTER=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IPSEC=m
-CONFIG_IPSEC_DEBUG=y
-CONFIG_IPSEC_DEBUG_DISABLE_DEFAULT=y
-CONFIG_IPSEC_TUNNEL=y
-CONFIG_TUX=m
-CONFIG_TUX_EXTCGI=y
-CONFIG_TUX_EXTENDED_LOG=y
-# CONFIG_TUX_DEBUG is not set
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_FWMARK=y
-CONFIG_IP_ROUTE_NAT=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_TOS=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_ROUTE_LARGE_TABLES=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_NET_IPIP=m
-CONFIG_NET_IPGRE=m
-CONFIG_NET_IPGRE_BROADCAST=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-# CONFIG_ARPD is not set
-CONFIG_INET_ECN=y
-CONFIG_SYN_COOKIES=y
-CONFIG_IP_IPSEC=m
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_PSD=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_IPLIMIT=m
-CONFIG_IP_NF_MATCH_UNCLEAN=m
-CONFIG_IP_NF_MATCH_STRING=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_MIRROR=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_NAT_AMANDA=m
-# CONFIG_IP_NF_NAT_LOCAL is not set
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_COMPAT_IPFWADM=m
-CONFIG_IP_NF_NAT_NEEDED=y
-
-#
-# IP: Virtual Server Configuration
-#
-CONFIG_IP_VS=m
-# CONFIG_IP_VS_DEBUG is not set
-CONFIG_IP_VS_TAB_BITS=12
-CONFIG_IP_VS_RR=m
-CONFIG_IP_VS_WRR=m
-CONFIG_IP_VS_LC=m
-CONFIG_IP_VS_WLC=m
-CONFIG_IP_VS_LBLC=m
-CONFIG_IP_VS_LBLCR=m
-CONFIG_IP_VS_DH=m
-CONFIG_IP_VS_SH=m
-CONFIG_IP_VS_SED=m
-CONFIG_IP_VS_NQ=m
-CONFIG_IP_VS_FTP=m
-CONFIG_IPV6=m
-# CONFIG_IPV6_DEBUG is not set
-CONFIG_IPV6_IM=y
-CONFIG_IPV6_MODULE_IP_GRE=y
-CONFIG_IPV6_ISATAP=y
-CONFIG_IPV6_PREFIXLIST=y
-CONFIG_IPV6_6TO4_NEXTHOP=y
-CONFIG_IPV6_PRIVACY=y
-CONFIG_IPV6_SUBTREES=y
-# CONFIG_IPV6_MLD6_ALL_DONE is not set
-# CONFIG_IPV6_NODEINFO is not set
-# CONFIG_IPV6_ZONE is not set
-CONFIG_IPV6_DROP_FAKE_V4MAPPED=y
-
-#
-# IPv6: Netfilter Configuration
-#
-CONFIG_IP6_NF_QUEUE=m
-CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_LIMIT=m
-CONFIG_IP6_NF_MATCH_MAC=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
-CONFIG_IP6_NF_MATCH_FRAG=m
-CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
-CONFIG_IP6_NF_MATCH_OWNER=m
-CONFIG_IP6_NF_MATCH_MARK=m
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
-CONFIG_IP6_NF_MATCH_LENGTH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=m
-CONFIG_IP6_NF_TARGET_REJECT=m
-CONFIG_IP6_NF_TARGET_LOG=m
-CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_MARK=m
-CONFIG_IPV6_IPSEC=y
-CONFIG_IPV6_IPSEC_TUNNEL=y
-CONFIG_IPV6_IPV6_TUNNEL=m
-CONFIG_IPV6_MOBILITY=m
-CONFIG_IPV6_MOBILITY_CN=m
-CONFIG_IPV6_MOBILITY_MN=m
-CONFIG_IPV6_MOBILITY_HA=m
-# CONFIG_IPV6_MOBILITY_DEBUG is not set
-# CONFIG_SHARED_IPV6_CARDS is not set
-CONFIG_KHTTPD=m
-CONFIG_KHTTPD_IPV6=y
-# CONFIG_ATM is not set
-CONFIG_VLAN_8021Q=m
-CONFIG_IPX=m
-# CONFIG_IPX_INTERN is not set
-CONFIG_ATALK=m
-
-#
-# Appletalk devices
-#
-CONFIG_DEV_APPLETALK=y
-CONFIG_COPS_DAYNA=y
-CONFIG_COPS_TANGENT=y
-CONFIG_IPDDP=m
-CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
-CONFIG_DECNET=m
-CONFIG_DECNET_SIOCGIFCONF=y
-# CONFIG_DECNET_ROUTER is not set
-CONFIG_BRIDGE=m
-CONFIG_X25=m
-CONFIG_LAPB=m
-# CONFIG_LLC is not set
-# CONFIG_NET_DIVERT is not set
-CONFIG_ECONET=m
-# CONFIG_ECONET_AUNUDP is not set
-# CONFIG_ECONET_NATIVE is not set
-CONFIG_WAN_ROUTER=m
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_CBQ=m
-CONFIG_NET_SCH_HTB=m
-CONFIG_NET_SCH_CSZ=m
-CONFIG_NET_SCH_PRIO=m
-CONFIG_NET_SCH_RED=m
-CONFIG_NET_SCH_SFQ=m
-CONFIG_NET_SCH_TEQL=m
-CONFIG_NET_SCH_TBF=m
-CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DSMARK=m
-CONFIG_NET_SCH_INGRESS=m
-CONFIG_NET_QOS=y
-CONFIG_NET_ESTIMATOR=y
-CONFIG_NET_CLS=y
-CONFIG_NET_CLS_TCINDEX=m
-CONFIG_NET_CLS_ROUTE4=m
-CONFIG_NET_CLS_ROUTE=y
-CONFIG_NET_CLS_FW=m
-CONFIG_NET_CLS_U32=m
-CONFIG_NET_CLS_RSVP=m
-CONFIG_NET_CLS_RSVP6=m
-CONFIG_NET_CLS_POLICE=y
-
-#
-# Network testing
-#
-CONFIG_NET_PKTGEN=m
-
-#
-# Telephony Support
-#
-CONFIG_PHONE=m
-CONFIG_PHONE_IXJ=m
-CONFIG_PHONE_IXJ_PCMCIA=m
-
-#
-# ATA/IDE/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-# CONFIG_BLK_DEV_HD_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_IDEDISK_MULTI_MODE=y
-CONFIG_IDEDISK_STROKE=y
-CONFIG_BLK_DEV_IDECS=m
-CONFIG_BLK_DEV_IDECD=m
-CONFIG_BLK_DEV_IDETAPE=m
-CONFIG_BLK_DEV_IDEFLOPPY=y
-CONFIG_BLK_DEV_IDESCSI=m
-# CONFIG_IDE_TASK_IOCTL is not set
-CONFIG_BLK_DEV_CMD640=y
-CONFIG_BLK_DEV_CMD640_ENHANCED=y
-# CONFIG_BLK_DEV_ISAPNP is not set
-CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_IDEPCI_SHARE_IRQ=y
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-CONFIG_BLK_DEV_OFFBOARD=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
-CONFIG_IDEDMA_ONLYDISK=y
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_PCI_WIP is not set
-# CONFIG_BLK_DEV_ADMA100 is not set
-CONFIG_BLK_DEV_AEC62XX=y
-CONFIG_BLK_DEV_ALI15X3=y
-# CONFIG_WDC_ALI15X3 is not set
-CONFIG_BLK_DEV_AMD74XX=y
-# CONFIG_AMD74XX_OVERRIDE is not set
-CONFIG_BLK_DEV_CMD64X=y
-CONFIG_BLK_DEV_TRIFLEX=y
-CONFIG_BLK_DEV_CY82C693=y
-CONFIG_BLK_DEV_CS5530=y
-CONFIG_BLK_DEV_HPT34X=y
-# CONFIG_HPT34X_AUTODMA is not set
-CONFIG_BLK_DEV_HPT366=y
-# CONFIG_BLK_DEV_PIIX is not set
-CONFIG_BLK_DEV_NS87415=y
-# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_PDC202XX_OLD=y
-CONFIG_PDC202XX_BURST=y
-CONFIG_BLK_DEV_PDC202XX_NEW=y
-CONFIG_PDC202XX_FORCE=y
-# CONFIG_BLK_DEV_RZ1000 is not set
-CONFIG_BLK_DEV_SC1200=y
-# CONFIG_BLK_DEV_SVWKS is not set
-CONFIG_BLK_DEV_SIIMAGE=y
-CONFIG_BLK_DEV_SIS5513=y
-CONFIG_BLK_DEV_SLC90E66=y
-CONFIG_BLK_DEV_TRM290=y
-CONFIG_BLK_DEV_VIA82CXXX=y
-CONFIG_BLK_DEV_CENATEK=y
-# CONFIG_IDE_CHIPSETS is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_DMA_NONPCI is not set
-CONFIG_BLK_DEV_PDC202XX=y
-CONFIG_BLK_DEV_IDE_MODES=y
-CONFIG_BLK_DEV_ATARAID=m
-CONFIG_BLK_DEV_ATARAID_PDC=m
-CONFIG_BLK_DEV_ATARAID_HPT=m
-CONFIG_BLK_DEV_ATARAID_SII=m
-
-#
-# SCSI support
-#
-CONFIG_SCSI=m
-CONFIG_BLK_DEV_SD=m
-CONFIG_SD_MAX_MAJORS=144
-CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
-CONFIG_BLK_DEV_SR=m
-# CONFIG_BLK_DEV_SR_VENDOR is not set
-CONFIG_SR_EXTRA_DEVS=4
-CONFIG_CHR_DEV_SCH=m
-CONFIG_CHR_DEV_SG=m
-# CONFIG_SCSI_DEBUG_QUEUES is not set
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-
-#
-# SCSI low-level drivers
-#
-CONFIG_BLK_DEV_3W_XXXX_RAID=m
-# CONFIG_SCSI_7000FASST is not set
-CONFIG_SCSI_ACARD=m
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AHA1740 is not set
-CONFIG_SCSI_AACRAID=m
-CONFIG_SCSI_AIC7XXX=m
-CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
-CONFIG_AIC7XXX_RESET_DELAY_MS=5000
-CONFIG_AIC7XXX_PROBE_EISA_VL=y
-# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
-# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
-CONFIG_AIC7XXX_DEBUG_MASK=0
-CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
-CONFIG_SCSI_AIC79XX=m
-CONFIG_AIC79XX_CMDS_PER_DEVICE=32
-CONFIG_AIC79XX_RESET_DELAY_MS=15000
-# CONFIG_AIC79XX_BUILD_FIRMWARE is not set
-# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
-# CONFIG_AIC79XX_DEBUG_ENABLE is not set
-CONFIG_AIC79XX_DEBUG_MASK=0
-CONFIG_AIC79XX_REG_PRETTY_PRINT=y
-CONFIG_SCSI_AIC7XXX_OLD=m
-CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y
-CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=24
-CONFIG_AIC7XXX_OLD_PROC_STATS=y
-CONFIG_SCSI_DPT_I2O=m
-CONFIG_SCSI_ADVANSYS=m
-CONFIG_SCSI_IN2000=m
-CONFIG_SCSI_AM53C974=m
-CONFIG_SCSI_MEGARAID=m
-CONFIG_SCSI_MEGARAID2=m
-CONFIG_SCSI_BUSLOGIC=m
-# CONFIG_SCSI_OMIT_FLASHPOINT is not set
-CONFIG_SCSI_CPQFCTS=m
-CONFIG_SCSI_DMX3191D=m
-# CONFIG_SCSI_DTC3280 is not set
-CONFIG_SCSI_EATA=m
-CONFIG_SCSI_EATA_TAGGED_QUEUE=y
-CONFIG_SCSI_EATA_LINKED_COMMANDS=y
-CONFIG_SCSI_EATA_MAX_TAGS=16
-CONFIG_SCSI_EATA_DMA=m
-CONFIG_SCSI_EATA_PIO=m
-CONFIG_SCSI_LPFC=m
-CONFIG_SCSI_FUTURE_DOMAIN=m
-CONFIG_SCSI_GDTH=m
-CONFIG_SCSI_GENERIC_NCR5380=m
-CONFIG_SCSI_GENERIC_NCR53C400=y
-CONFIG_SCSI_G_NCR5380_PORT=y
-# CONFIG_SCSI_G_NCR5380_MEM is not set
-CONFIG_SCSI_IPS_OLD=m
-CONFIG_SCSI_IPS=m
-CONFIG_SCSI_INITIO=m
-CONFIG_SCSI_INIA100=m
-CONFIG_SCSI_PPA=m
-CONFIG_SCSI_IMM=m
-# CONFIG_SCSI_IZIP_EPP16 is not set
-# CONFIG_SCSI_IZIP_SLOW_CTR is not set
-CONFIG_PPSCSI=m
-CONFIG_PPSCSI_T348=m
-CONFIG_PPSCSI_T358=m
-CONFIG_PPSCSI_VPI0=m
-CONFIG_PPSCSI_VPI2=m
-CONFIG_PPSCSI_ONSCSI=m
-CONFIG_PPSCSI_SPARCSI=m
-CONFIG_PPSCSI_EPSA2=m
-CONFIG_PPSCSI_EPST=m
-# CONFIG_SCSI_NCR53C406A is not set
-CONFIG_SCSI_NCR53C7xx=m
-# CONFIG_SCSI_NCR53C7xx_sync is not set
-CONFIG_SCSI_NCR53C7xx_FAST=y
-CONFIG_SCSI_NCR53C7xx_DISCONNECT=y
-CONFIG_SCSI_SYM53C8XX_2=m
-CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
-CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
-CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
-CONFIG_SCSI_NCR53C8XX=m
-CONFIG_SCSI_SYM53C8XX=m
-CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
-CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
-CONFIG_SCSI_NCR53C8XX_SYNC=80
-CONFIG_SCSI_NCR53C8XX_PROFILE=y
-# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
-CONFIG_SCSI_NCR53C8XX_PQS_PDS=y
-# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
-# CONFIG_SCSI_PAS16 is not set
-CONFIG_SCSI_PCI2000=m
-CONFIG_SCSI_PCI2220I=m
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-CONFIG_SCSI_QLOGIC_ISP=m
-CONFIG_SCSI_QLOGIC_FC=m
-CONFIG_SCSI_QLOGIC_FC_FIRMWARE=y
-CONFIG_SCSI_QLOGIC_1280=m
-CONFIG_SCSI_QLOGIC_QLA2XXX=y
-CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2100=m
-CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2200=m
-CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2300=m
-CONFIG_SCSI_SEAGATE=m
-CONFIG_SCSI_SIM710=m
-CONFIG_SCSI_SYM53C416=m
-CONFIG_SCSI_DC395x_TRMS1040=m
-CONFIG_SCSI_DC390T=m
-# CONFIG_SCSI_DC390T_NOGENSUPP is not set
-# CONFIG_SCSI_T128 is not set
-CONFIG_SCSI_U14_34F=m
-CONFIG_SCSI_U14_34F_LINKED_COMMANDS=y
-CONFIG_SCSI_U14_34F_MAX_TAGS=8
-CONFIG_SCSI_ULTRASTOR=m
-CONFIG_SCSI_NSP32=m
-CONFIG_SCSI_DEBUG=m
-
-#
-# PCMCIA SCSI adapter support
-#
-CONFIG_SCSI_PCMCIA=y
-CONFIG_PCMCIA_AHA152X=m
-CONFIG_PCMCIA_FDOMAIN=m
-CONFIG_PCMCIA_NINJA_SCSI=m
-CONFIG_PCMCIA_QLOGIC=m
-
-#
-# Fusion MPT device support
-#
-CONFIG_FUSION=m
-# CONFIG_FUSION_BOOT is not set
-CONFIG_FUSION_MAX_SGE=40
-CONFIG_FUSION_ISENSE=m
-CONFIG_FUSION_CTL=m
-CONFIG_FUSION_LAN=m
-CONFIG_NET_FC=y
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-CONFIG_IEEE1394=m
-CONFIG_IEEE1394_PCILYNX=m
-CONFIG_IEEE1394_OHCI1394=m
-CONFIG_IEEE1394_VIDEO1394=m
-CONFIG_IEEE1394_SBP2=m
-# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
-CONFIG_IEEE1394_ETH1394=m
-CONFIG_IEEE1394_DV1394=m
-CONFIG_IEEE1394_RAWIO=m
-CONFIG_IEEE1394_CMP=m
-CONFIG_IEEE1394_AMDTP=m
-# CONFIG_IEEE1394_VERBOSEDEBUG is not set
-# CONFIG_IEEE1394_OUI_DB is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-CONFIG_ARCNET=m
-CONFIG_ARCNET_1201=m
-CONFIG_ARCNET_1051=m
-CONFIG_ARCNET_RAW=m
-CONFIG_ARCNET_COM90xx=m
-CONFIG_ARCNET_COM90xxIO=m
-CONFIG_ARCNET_RIM_I=m
-CONFIG_ARCNET_COM20020=m
-# CONFIG_ARCNET_COM20020_ISA is not set
-CONFIG_ARCNET_COM20020_PCI=m
-CONFIG_DUMMY=m
-CONFIG_BONDING=m
-CONFIG_EQUALIZER=m
-CONFIG_TUN=m
-CONFIG_ETHERTAP=m
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_SUNLANCE is not set
-CONFIG_HAPPYMEAL=m
-# CONFIG_SUNBMAC is not set
-# CONFIG_SUNQE is not set
-CONFIG_SUNGEM=m
-CONFIG_NET_VENDOR_3COM=y
-# CONFIG_EL1 is not set
-# CONFIG_EL2 is not set
-# CONFIG_ELPLUS is not set
-# CONFIG_EL16 is not set
-# CONFIG_ELMC is not set
-# CONFIG_ELMC_II is not set
-CONFIG_VORTEX=m
-CONFIG_TYPHOON=m
-# CONFIG_LANCE is not set
-CONFIG_NET_VENDOR_SMC=y
-# CONFIG_WD80x3 is not set
-# CONFIG_ULTRAMCA is not set
-# CONFIG_ULTRA is not set
-# CONFIG_ULTRA32 is not set
-# CONFIG_SMC9194 is not set
-CONFIG_NET_VENDOR_RACAL=y
-# CONFIG_NI5010 is not set
-# CONFIG_NI52 is not set
-# CONFIG_NI65 is not set
-CONFIG_HP100=m
-# CONFIG_NET_ISA is not set
-CONFIG_NET_PCI=y
-CONFIG_PCNET32=m
-CONFIG_PCNET32_OLD=m
-CONFIG_AMD8111_ETH=m
-CONFIG_ADAPTEC_STARFIRE=m
-# CONFIG_APRICOT is not set
-CONFIG_NET_BCM4400=m
-# CONFIG_CS89x0 is not set
-CONFIG_TULIP=m
-# CONFIG_TULIP_MWI is not set
-# CONFIG_TULIP_MMIO is not set
-CONFIG_DE4X5=m
-CONFIG_DGRS=m
-CONFIG_DM9102=m
-CONFIG_EEPRO100=m
-# CONFIG_EEPRO100_PIO is not set
-CONFIG_E100=m
-# CONFIG_LNE390 is not set
-CONFIG_FEALNX=m
-CONFIG_NATSEMI=m
-CONFIG_NETGEAR_GA621=m
-CONFIG_NETGEAR_GA622=m
-CONFIG_NE2K_PCI=m
-# CONFIG_NE3210 is not set
-# CONFIG_ES3210 is not set
-CONFIG_8139CP=m
-CONFIG_8139TOO=m
-# CONFIG_8139TOO_PIO is not set
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-CONFIG_8139TOO_8129=y
-# CONFIG_8139_OLD_RX_RESET is not set
-CONFIG_SIS900=m
-CONFIG_EPIC100=m
-CONFIG_SUNDANCE=m
-# CONFIG_SUNDANCE_MMIO is not set
-CONFIG_TLAN=m
-CONFIG_TC35815=m
-CONFIG_VIA_RHINE=m
-# CONFIG_VIA_RHINE_MMIO is not set
-CONFIG_WINBOND_840=m
-CONFIG_NET_POCKET=y
-# CONFIG_DE600 is not set
-# CONFIG_DE620 is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-CONFIG_ACENIC=m
-# CONFIG_ACENIC_OMIT_TIGON_I is not set
-CONFIG_DL2K=m
-CONFIG_E1000=m
-# CONFIG_MYRI_SBUS is not set
-CONFIG_NS83820=m
-CONFIG_HAMACHI=m
-CONFIG_YELLOWFIN=m
-CONFIG_R8169=m
-CONFIG_SK98LIN=m
-CONFIG_SK98LIN_T1=y
-CONFIG_SK98LIN_T3=y
-CONFIG_SK98LIN_T8=y
-CONFIG_SK98LIN_T6=y
-CONFIG_SK98LIN_T9=y
-CONFIG_SK98LIN_T4=y
-CONFIG_SK98LIN_T7=y
-CONFIG_SK98LIN_T2=y
-CONFIG_SK98LIN_T5=y
-CONFIG_SK9DLIN=m
-CONFIG_TIGON3=m
-CONFIG_NET_BROADCOM=m
-CONFIG_FDDI=y
-CONFIG_DEFXX=m
-CONFIG_SKFP=m
-CONFIG_NETCONSOLE=m
-CONFIG_HIPPI=y
-CONFIG_ROADRUNNER=m
-CONFIG_ROADRUNNER_LARGE_RINGS=y
-CONFIG_PLIP=m
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPPOE=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-CONFIG_SLIP_MODE_SLIP6=y
-
-#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-CONFIG_STRIP=m
-CONFIG_WAVELAN=m
-CONFIG_AIRONET4500=m
-CONFIG_AIRONET4500_NONCS=m
-CONFIG_AIRONET4500_PNP=y
-CONFIG_AIRONET4500_PCI=y
-CONFIG_AIRONET4500_ISA=y
-CONFIG_AIRONET4500_I365=y
-CONFIG_AIRONET4500_PROC=m
-CONFIG_AIRO=m
-CONFIG_HERMES=m
-CONFIG_PLX_HERMES=m
-CONFIG_PCI_HERMES=m
-CONFIG_PCMCIA_HERMES=m
-CONFIG_AIRO_CS=m
-CONFIG_NET_WIRELESS=y
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-CONFIG_NET_FC=y
-CONFIG_IPHASE5526=m
-CONFIG_RCPCI=m
-CONFIG_SHAPER=m
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# PCMCIA network device support
-#
-CONFIG_NET_PCMCIA=y
-CONFIG_PCMCIA_3C589=m
-CONFIG_PCMCIA_3C574=m
-CONFIG_PCMCIA_FMVJ18X=m
-CONFIG_PCMCIA_PCNET=m
-CONFIG_PCMCIA_AXNET=m
-CONFIG_PCMCIA_NMCLAN=m
-CONFIG_PCMCIA_SMC91C92=m
-CONFIG_PCMCIA_XIRC2PS=m
-CONFIG_ARCNET_COM20020_CS=m
-# CONFIG_PCMCIA_IBMTR is not set
-CONFIG_PCMCIA_XIRCOM=m
-CONFIG_PCMCIA_XIRTULIP=m
-CONFIG_NET_PCMCIA_RADIO=y
-CONFIG_PCMCIA_RAYCS=m
-CONFIG_PCMCIA_NETWAVE=m
-CONFIG_PCMCIA_WAVELAN=m
-CONFIG_AIRONET4500_CS=m
-
-#
-# Amateur Radio support
-#
-CONFIG_HAMRADIO=y
-CONFIG_AX25=m
-CONFIG_AX25_DAMA_SLAVE=y
-CONFIG_NETROM=m
-CONFIG_ROSE=m
-
-#
-# AX.25 network device drivers
-#
-CONFIG_MKISS=m
-CONFIG_6PACK=m
-CONFIG_BPQETHER=m
-CONFIG_SCC_DELAY=y
-CONFIG_SCC_TRXECHO=y
-CONFIG_BAYCOM_SER_FDX=m
-CONFIG_BAYCOM_SER_HDX=m
-CONFIG_BAYCOM_PAR=m
-CONFIG_BAYCOM_EPP=m
-CONFIG_SOUNDMODEM=m
-CONFIG_SOUNDMODEM_SBC=y
-CONFIG_SOUNDMODEM_WSS=y
-CONFIG_SOUNDMODEM_AFSK1200=y
-CONFIG_SOUNDMODEM_AFSK2400_7=y
-CONFIG_SOUNDMODEM_AFSK2400_8=y
-CONFIG_SOUNDMODEM_AFSK2666=y
-CONFIG_SOUNDMODEM_HAPN4800=y
-CONFIG_SOUNDMODEM_PSK4800=y
-CONFIG_SOUNDMODEM_FSK9600=y
-CONFIG_YAM=m
-
-#
-# IrDA (infrared) support
-#
-CONFIG_IRDA=m
-CONFIG_IRLAN=m
-CONFIG_IRNET=m
-CONFIG_IRCOMM=m
-CONFIG_IRDA_ULTRA=y
-CONFIG_IRDA_CACHE_LAST_LSAP=y
-# CONFIG_IRDA_FAST_RR is not set
-# CONFIG_IRDA_DEBUG is not set
-
-#
-# Infrared-port device drivers
-#
-CONFIG_IRTTY_SIR=m
-CONFIG_IRPORT_SIR=m
-CONFIG_DONGLE=y
-CONFIG_ESI_DONGLE=m
-CONFIG_ACTISYS_DONGLE=m
-CONFIG_TEKRAM_DONGLE=m
-CONFIG_GIRBIL_DONGLE=m
-CONFIG_LITELINK_DONGLE=m
-CONFIG_MCP2120_DONGLE=m
-CONFIG_OLD_BELKIN_DONGLE=m
-CONFIG_ACT200L_DONGLE=m
-CONFIG_MA600_DONGLE=m
-CONFIG_USB_IRDA=m
-CONFIG_NSC_FIR=m
-CONFIG_WINBOND_FIR=m
-# CONFIG_TOSHIBA_OLD is not set
-CONFIG_TOSHIBA_FIR=m
-CONFIG_SMC_IRCC_FIR=m
-CONFIG_ALI_FIR=m
-CONFIG_VLSI_FIR=m
-
-#
-# ISDN subsystem
-#
-CONFIG_ISDN=m
-CONFIG_ISDN_BOOL=y
-CONFIG_ISDN_PPP=y
-CONFIG_IPPP_FILTER=y
-CONFIG_ISDN_PPP_VJ=y
-CONFIG_ISDN_MPP=y
-CONFIG_ISDN_PPP_BSDCOMP=m
-CONFIG_ISDN_AUDIO=y
-CONFIG_ISDN_TTY_FAX=y
-CONFIG_ISDN_X25=y
-
-#
-# ISDN feature submodules
-#
-CONFIG_ISDN_DRV_LOOP=m
-CONFIG_ISDN_DIVERSION=m
-
-#
-# Passive ISDN cards
-#
-CONFIG_ISDN_DRV_HISAX=m
-CONFIG_ISDN_HISAX=y
-CONFIG_HISAX_EURO=y
-CONFIG_DE_AOC=y
-# CONFIG_HISAX_NO_SENDCOMPLETE is not set
-# CONFIG_HISAX_NO_LLC is not set
-# CONFIG_HISAX_NO_KEYPAD is not set
-CONFIG_HISAX_1TR6=y
-CONFIG_HISAX_NI1=y
-CONFIG_HISAX_MAX_CARDS=8
-CONFIG_HISAX_TELESPCI=y
-CONFIG_HISAX_S0BOX=y
-CONFIG_HISAX_FRITZPCI=y
-CONFIG_HISAX_AVM_A1_PCMCIA=y
-CONFIG_HISAX_ELSA=y
-CONFIG_HISAX_DIEHLDIVA=y
-CONFIG_HISAX_SEDLBAUER=y
-CONFIG_HISAX_NETJET=y
-CONFIG_HISAX_NETJET_U=y
-CONFIG_HISAX_NICCY=y
-CONFIG_HISAX_BKM_A4T=y
-CONFIG_HISAX_SCT_QUADRO=y
-CONFIG_HISAX_GAZEL=y
-CONFIG_HISAX_HFC_PCI=y
-CONFIG_HISAX_W6692=y
-CONFIG_HISAX_HFC_SX=y
-CONFIG_HISAX_ENTERNOW_PCI=y
-# CONFIG_HISAX_DEBUG is not set
-# CONFIG_HISAX_TELES_CS is not set
-CONFIG_HISAX_SEDLBAUER_CS=m
-CONFIG_HISAX_ELSA_CS=m
-# CONFIG_HISAX_AVM_A1_CS is not set
-CONFIG_HISAX_ST5481=m
-CONFIG_HISAX_FRITZ_PCIPNP=m
-CONFIG_USB_AUERISDN=m
-
-#
-# Active ISDN cards
-#
-CONFIG_ISDN_DRV_ICN=m
-CONFIG_ISDN_DRV_PCBIT=m
-CONFIG_ISDN_DRV_SC=m
-CONFIG_ISDN_DRV_ACT2000=m
-CONFIG_ISDN_DRV_EICON=y
-CONFIG_ISDN_DRV_EICON_DIVAS=m
-CONFIG_ISDN_DRV_EICON_OLD=m
-CONFIG_ISDN_DRV_EICON_PCI=y
-CONFIG_ISDN_DRV_EICON_ISA=y
-CONFIG_ISDN_DRV_TPAM=m
-CONFIG_ISDN_CAPI=m
-CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
-CONFIG_ISDN_CAPI_MIDDLEWARE=y
-CONFIG_ISDN_CAPI_CAPI20=m
-CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
-CONFIG_ISDN_CAPI_CAPIFS=m
-CONFIG_ISDN_CAPI_CAPIDRV=m
-# CONFIG_ISDN_DRV_AVMB1_B1ISA is not set
-CONFIG_ISDN_DRV_AVMB1_B1PCI=m
-CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
-# CONFIG_ISDN_DRV_AVMB1_T1ISA is not set
-CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
-CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
-CONFIG_ISDN_DRV_AVMB1_T1PCI=m
-CONFIG_ISDN_DRV_AVMB1_C4=m
-CONFIG_HYSDN=m
-CONFIG_HYSDN_CAPI=y
-
-#
-# Input core support
-#
-CONFIG_INPUT=m
-CONFIG_INPUT_KEYBDEV=m
-CONFIG_INPUT_MOUSEDEV=m
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-CONFIG_INPUT_JOYDEV=m
-CONFIG_INPUT_EVDEV=m
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_ECC=m
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-CONFIG_SERIAL_EXTENDED=y
-CONFIG_SERIAL_MANY_PORTS=y
-CONFIG_SERIAL_SHARE_IRQ=y
-# CONFIG_SERIAL_DETECT_IRQ is not set
-CONFIG_SERIAL_MULTIPORT=y
-CONFIG_HUB6=y
-CONFIG_SERIAL_NONSTANDARD=y
-CONFIG_COMPUTONE=m
-CONFIG_ROCKETPORT=m
-CONFIG_CYCLADES=m
-# CONFIG_CYZ_INTR is not set
-# CONFIG_ESPSERIAL is not set
-CONFIG_MOXA_INTELLIO=m
-CONFIG_MOXA_SMARTIO=m
-CONFIG_ISI=m
-CONFIG_SYNCLINK=m
-CONFIG_SYNCLINKMP=m
-CONFIG_N_HDLC=m
-CONFIG_RISCOM8=m
-CONFIG_STALDRV=y
-CONFIG_STALLION=m
-CONFIG_ISTALLION=m
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-CONFIG_PRINTER=m
-# CONFIG_LP_CONSOLE is not set
-CONFIG_PPDEV=m
-CONFIG_TIPAR=m
-
-#
-# I2C support
-#
-CONFIG_I2C=m
-CONFIG_I2C_ALGOBIT=m
-CONFIG_I2C_PHILIPSPAR=m
-# CONFIG_I2C_ELV is not set
-# CONFIG_I2C_VELLEMAN is not set
-CONFIG_SCx200_I2C=m
-CONFIG_SCx200_I2C_SCL=12
-CONFIG_SCx200_I2C_SDA=13
-CONFIG_SCx200_ACB=m
-CONFIG_I2C_ALGOPCF=m
-# CONFIG_I2C_ELEKTOR is not set
-CONFIG_I2C_MAINBOARD=y
-CONFIG_I2C_ALI1535=m
-CONFIG_I2C_ALI15X3=m
-CONFIG_I2C_HYDRA=m
-CONFIG_I2C_AMD756=m
-CONFIG_I2C_AMD8111=m
-CONFIG_I2C_I801=m
-# CONFIG_I2C_I810 is not set
-CONFIG_I2C_PIIX4=m
-CONFIG_I2C_SIS5595=m
-CONFIG_I2C_SIS630=m
-CONFIG_I2C_SIS645=m
-CONFIG_I2C_SAVAGE4=m
-CONFIG_I2C_VIA=m
-CONFIG_I2C_VIAPRO=m
-CONFIG_I2C_VOODOO3=m
-CONFIG_I2C_ISA=m
-CONFIG_I2C_CHARDEV=m
-CONFIG_I2C_PROC=m
-
-#
-# Hardware sensors support
-#
-CONFIG_SENSORS=y
-CONFIG_SENSORS_ADM1021=m
-CONFIG_SENSORS_ADM1024=m
-CONFIG_SENSORS_ADM1025=m
-CONFIG_SENSORS_ADM1026=m
-CONFIG_SENSORS_ADM9240=m
-CONFIG_SENSORS_DS1621=m
-CONFIG_SENSORS_FSCPOS=m
-CONFIG_SENSORS_FSCSCY=m
-CONFIG_SENSORS_GL518SM=m
-CONFIG_SENSORS_GL520SM=m
-CONFIG_SENSORS_MAXILIFE=m
-CONFIG_SENSORS_IT87=m
-CONFIG_SENSORS_MTP008=m
-CONFIG_SENSORS_LM75=m
-CONFIG_SENSORS_LM78=m
-CONFIG_SENSORS_LM80=m
-CONFIG_SENSORS_LM85=m
-CONFIG_SENSORS_LM87=m
-# CONFIG_SENSORS_LM92 is not set
-CONFIG_SENSORS_SIS5595=m
-# CONFIG_SENSORS_SMSC47M1 is not set
-CONFIG_SENSORS_THMC50=m
-CONFIG_SENSORS_VIA686A=m
-CONFIG_SENSORS_VT1211=m
-CONFIG_SENSORS_VT8231=m
-CONFIG_SENSORS_W83781D=m
-CONFIG_SENSORS_OTHER=y
-CONFIG_SENSORS_BT869=m
-CONFIG_SENSORS_DDCMON=m
-CONFIG_SENSORS_EEPROM=m
-CONFIG_SENSORS_MATORB=m
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-
-#
-# Mice
-#
-CONFIG_BUSMOUSE=m
-CONFIG_ATIXL_BUSMOUSE=m
-CONFIG_LOGIBUSMOUSE=m
-CONFIG_MS_BUSMOUSE=m
-CONFIG_MOUSE=y
-CONFIG_PSMOUSE=y
-CONFIG_82C710_MOUSE=y
-CONFIG_PC110_PAD=m
-CONFIG_MK712_MOUSE=m
-
-#
-# Joysticks
-#
-CONFIG_INPUT_GAMEPORT=m
-CONFIG_INPUT_NS558=m
-CONFIG_INPUT_LIGHTNING=m
-CONFIG_INPUT_PCIGAME=m
-CONFIG_INPUT_CS461X=m
-CONFIG_INPUT_EMU10K1=m
-CONFIG_INPUT_FM801=m
-CONFIG_INPUT_SERIO=m
-CONFIG_INPUT_SERPORT=m
-CONFIG_INPUT_ANALOG=m
-CONFIG_INPUT_A3D=m
-CONFIG_INPUT_ADI=m
-CONFIG_INPUT_COBRA=m
-CONFIG_INPUT_GF2K=m
-CONFIG_INPUT_GRIP=m
-CONFIG_INPUT_INTERACT=m
-CONFIG_INPUT_TMDC=m
-CONFIG_INPUT_SIDEWINDER=m
-CONFIG_INPUT_IFORCE_USB=m
-CONFIG_INPUT_IFORCE_232=m
-CONFIG_INPUT_WARRIOR=m
-CONFIG_INPUT_MAGELLAN=m
-CONFIG_INPUT_SPACEORB=m
-CONFIG_INPUT_SPACEBALL=m
-CONFIG_INPUT_STINGER=m
-CONFIG_INPUT_DB9=m
-CONFIG_INPUT_GAMECON=m
-CONFIG_INPUT_TURBOGRAFX=m
-CONFIG_QIC02_TAPE=m
-CONFIG_QIC02_DYNCONF=y
-CONFIG_IPMI_HANDLER=m
-CONFIG_IPMI_PANIC_EVENT=y
-CONFIG_IPMI_DEVICE_INTERFACE=m
-CONFIG_IPMI_KCS=m
-CONFIG_IPMI_WATCHDOG=m
-
-#
-# Watchdog Cards
-#
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_ACQUIRE_WDT=m
-CONFIG_ADVANTECH_WDT=m
-CONFIG_ALIM1535_WDT=m
-CONFIG_ALIM7101_WDT=m
-CONFIG_SC520_WDT=m
-CONFIG_PCWATCHDOG=m
-CONFIG_EUROTECH_WDT=m
-CONFIG_IB700_WDT=m
-CONFIG_WAFER_WDT=m
-# CONFIG_I810_TCO is not set
-CONFIG_MIXCOMWD=m
-CONFIG_60XX_WDT=m
-CONFIG_SC1200_WDT=m
-CONFIG_SCx200_WDT=m
-CONFIG_SOFT_WATCHDOG=m
-CONFIG_W83877F_WDT=m
-CONFIG_WDT=m
-CONFIG_WDTPCI=m
-CONFIG_WDT_501=y
-CONFIG_WDT_501_FAN=y
-CONFIG_MACHZ_WDT=m
-CONFIG_DEADMAN=m
-CONFIG_HANGCHECK_TIMER=m
-CONFIG_AMD7XX_TCO=m
-CONFIG_SCx200_GPIO=m
-CONFIG_AMD_RNG=m
-CONFIG_INTEL_RNG=m
-CONFIG_AMD_PM768=m
-CONFIG_NVRAM=m
-CONFIG_RTC=y
-CONFIG_DTLK=m
-CONFIG_R3964=m
-CONFIG_APPLICOM=m
-
-#
-# Ftape, the floppy tape device driver
-#
-CONFIG_FTAPE=m
-CONFIG_ZFTAPE=m
-CONFIG_ZFT_DFLT_BLK_SZ=10240
-CONFIG_ZFT_COMPRESSOR=m
-CONFIG_FT_NR_BUFFERS=3
-CONFIG_FT_PROC_FS=y
-CONFIG_FT_NORMAL_DEBUG=y
-# CONFIG_FT_FULL_DEBUG is not set
-# CONFIG_FT_NO_TRACE is not set
-# CONFIG_FT_NO_TRACE_AT_ALL is not set
-CONFIG_FT_STD_FDC=y
-# CONFIG_FT_MACH2 is not set
-# CONFIG_FT_PROBE_FC10 is not set
-# CONFIG_FT_ALT_FDC is not set
-CONFIG_FT_FDC_THR=8
-CONFIG_FT_FDC_MAX_RATE=2000
-CONFIG_FT_ALPHA_CLOCK=0
-CONFIG_AGP=y
-CONFIG_AGP_AMD_8151=y
-# CONFIG_AGP_INTEL is not set
-# CONFIG_AGP_I810 is not set
-# CONFIG_AGP_VIA is not set
-# CONFIG_AGP_AMD is not set
-# CONFIG_AGP_SIS is not set
-# CONFIG_AGP_ALI is not set
-# CONFIG_AGP_SWORKS is not set
-# CONFIG_AGP_NVIDIA is not set
-CONFIG_DRM=y
-# CONFIG_DRM_OLD is not set
-CONFIG_DRM_NEW=y
-CONFIG_DRM_TDFX=m
-CONFIG_DRM_R128=m
-CONFIG_DRM_RADEON=m
-CONFIG_DRM_I810=m
-# CONFIG_DRM_I810_XFREE_41 is not set
-CONFIG_DRM_I830=m
-CONFIG_DRM_MGA=m
-# CONFIG_DRM_SIS is not set
-
-#
-# PCMCIA character devices
-#
-CONFIG_PCMCIA_SERIAL_CS=m
-CONFIG_SYNCLINK_CS=m
-CONFIG_MWAVE=m
-
-#
-# Multimedia devices
-#
-CONFIG_VIDEO_DEV=m
-
-#
-# Video For Linux
-#
-CONFIG_VIDEO_PROC_FS=y
-CONFIG_I2C_PARPORT=m
-CONFIG_VIDEO_BT848=m
-CONFIG_VIDEO_PMS=m
-CONFIG_VIDEO_BWQCAM=m
-CONFIG_VIDEO_CQCAM=m
-CONFIG_VIDEO_W9966=m
-CONFIG_VIDEO_CPIA=m
-CONFIG_VIDEO_CPIA_PP=m
-CONFIG_VIDEO_CPIA_USB=m
-CONFIG_VIDEO_SAA5249=m
-CONFIG_TUNER_3036=m
-CONFIG_VIDEO_STRADIS=m
-CONFIG_VIDEO_ZORAN=m
-CONFIG_VIDEO_ZORAN_BUZ=m
-CONFIG_VIDEO_ZORAN_DC10=m
-CONFIG_VIDEO_ZORAN_LML33=m
-CONFIG_VIDEO_ZR36120=m
-# CONFIG_VIDEO_MEYE is not set
-
-#
-# Radio Adapters
-#
-CONFIG_RADIO_GEMTEK_PCI=m
-CONFIG_RADIO_MAXIRADIO=m
-CONFIG_RADIO_MAESTRO=m
-CONFIG_RADIO_MIROPCM20=m
-# CONFIG_DXR3 is not set
-
-#
-# File systems
-#
-CONFIG_QUOTA=y
-CONFIG_QFMT_V1=m
-CONFIG_QFMT_V2=m
-CONFIG_QIFACE_COMPAT=y
-# CONFIG_QIFACE_V1 is not set
-CONFIG_QIFACE_V2=y
-CONFIG_AUTOFS_FS=m
-CONFIG_AUTOFS4_FS=m
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-CONFIG_REISERFS_PROC_INFO=y
-CONFIG_REISERFS_FS_XATTR=y
-CONFIG_REISERFS_FS_XATTR_USER=y
-CONFIG_REISERFS_FS_XATTR_TRUSTED=y
-CONFIG_REISERFS_FS_POSIX_ACL=y
-CONFIG_ADFS_FS=m
-# CONFIG_ADFS_FS_RW is not set
-CONFIG_AFFS_FS=m
-CONFIG_HFS_FS=m
-CONFIG_HFSPLUS_FS=m
-CONFIG_BEFS_FS=m
-# CONFIG_BEFS_DEBUG is not set
-CONFIG_BFS_FS=m
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-CONFIG_EXT3_FS_XATTR_SHARING=y
-CONFIG_EXT3_FS_XATTR_USER=y
-CONFIG_EXT3_FS_XATTR_TRUSTED=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_JBD=y
-CONFIG_JBD_DEBUG=y
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_UMSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_FATX_FS=m
-CONFIG_EFS_FS=m
-CONFIG_JFFS_FS=m
-CONFIG_JFFS_FS_VERBOSE=0
-CONFIG_JFFS_PROC_FS=y
-CONFIG_JFFS2_FS=m
-CONFIG_JFFS2_FS_DEBUG=0
-CONFIG_CRAMFS=m
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_JFS_FS=m
-CONFIG_JFS_POSIX_ACL=y
-# CONFIG_JFS_DEBUG is not set
-CONFIG_JFS_STATISTICS=y
-CONFIG_MINIX_FS=y
-CONFIG_VXFS_FS=m
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_DEBUG is not set
-# CONFIG_NTFS_RW is not set
-CONFIG_HPFS_FS=m
-CONFIG_PROC_FS=y
-CONFIG_PROC_CONFIG=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
-CONFIG_QNX4FS_FS=m
-# CONFIG_QNX4FS_RW is not set
-CONFIG_ROMFS_FS=m
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_XATTR_SHARING=y
-CONFIG_EXT2_FS_XATTR_USER=y
-CONFIG_EXT2_FS_XATTR_TRUSTED=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_SYSV_FS=m
-CONFIG_UDF_FS=m
-CONFIG_UDF_RW=y
-CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
-CONFIG_XFS_FS=m
-CONFIG_XFS_POSIX_ACL=y
-# CONFIG_XFS_RT is not set
-CONFIG_XFS_QUOTA=y
-CONFIG_XFS_DMAPI=y
-# CONFIG_XFS_DEBUG is not set
-# CONFIG_PAGEBUF_DEBUG is not set
-# CONFIG_OCFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_CODA_FS=m
-CONFIG_INTERMEZZO_FS=m
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_ACL=y
-CONFIG_NFS_DIRECTIO=y
-CONFIG_ROOT_NFS=y
-CONFIG_NFSD=m
-CONFIG_NFSD_V3=y
-CONFIG_NFSD_ACL=y
-CONFIG_NFSD_TCP=y
-CONFIG_NFSD_FHALIAS=y
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_CIFS=m
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
-CONFIG_SMB_NLS_REMOTE="cp437"
-CONFIG_NCP_FS=m
-CONFIG_NCPFS_PACKET_SIGNING=y
-CONFIG_NCPFS_IOCTL_LOCKING=y
-CONFIG_NCPFS_STRONG=y
-CONFIG_NCPFS_NFS_NS=y
-CONFIG_NCPFS_OS2_NS=y
-CONFIG_NCPFS_SMALLDOS=y
-CONFIG_NCPFS_NLS=y
-CONFIG_NCPFS_EXTRAS=y
-CONFIG_ZISOFS_FS=y
-CONFIG_FS_MBCACHE=y
-CONFIG_FS_POSIX_ACL=y
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-CONFIG_OSF_PARTITION=y
-# CONFIG_AMIGA_PARTITION is not set
-CONFIG_ATARI_PARTITION=y
-CONFIG_MAC_PARTITION=y
-CONFIG_XBOX_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
-CONFIG_BSD_DISKLABEL=y
-# CONFIG_MINIX_SUBPARTITION is not set
-CONFIG_SOLARIS_X86_PARTITION=y
-CONFIG_UNIXWARE_DISKLABEL=y
-# CONFIG_LDM_PARTITION is not set
-CONFIG_SGI_PARTITION=y
-CONFIG_ULTRIX_PARTITION=y
-CONFIG_SUN_PARTITION=y
-CONFIG_EFI_PARTITION=y
-CONFIG_SMB_NLS=y
-CONFIG_NLS=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=m
-
-#
-# Console drivers
-#
-CONFIG_VGA_CONSOLE=y
-CONFIG_VIDEO_SELECT=y
-CONFIG_MDA_CONSOLE=m
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FB_RIVA=m
-CONFIG_FB_CLGEN=m
-CONFIG_FB_PM2=m
-CONFIG_FB_PM2_FIFO_DISCONNECT=y
-CONFIG_FB_PM2_PCI=y
-CONFIG_FB_PM3=m
-# CONFIG_UNICON is not set
-# CONFIG_UNICON_GB is not set
-# CONFIG_UNICON_GBK is not set
-# CONFIG_UNICON_BIG5 is not set
-# CONFIG_UNICON_JIS is not set
-# CONFIG_UNICON_KSCM is not set
-CONFIG_FB_CYBER2000=m
-CONFIG_FB_VESA=y
-CONFIG_FB_VGA16=m
-CONFIG_FB_HGA=m
-CONFIG_VIDEO_SELECT=y
-CONFIG_FB_MATROX=m
-CONFIG_FB_MATROX_MILLENIUM=y
-CONFIG_FB_MATROX_MYSTIQUE=y
-CONFIG_FB_MATROX_G450=y
-CONFIG_FB_MATROX_G100=y
-CONFIG_FB_MATROX_I2C=m
-CONFIG_FB_MATROX_MAVEN=m
-CONFIG_FB_MATROX_PROC=m
-CONFIG_FB_MATROX_MULTIHEAD=y
-CONFIG_FB_ATY=m
-CONFIG_FB_ATY_GX=y
-CONFIG_FB_ATY_CT=y
-CONFIG_FB_RADEON=m
-CONFIG_FB_ATY128=m
-# CONFIG_FB_INTEL is not set
-# CONFIG_FB_SIS is not set
-CONFIG_FB_NEOMAGIC=m
-CONFIG_FB_VMWARE_SVGA=m
-CONFIG_FB_3DFX=m
-CONFIG_FB_VOODOO1=m
-CONFIG_FB_TRIDENT=m
-# CONFIG_FB_VIRTUAL is not set
-CONFIG_FBCON_SPLASHSCREEN=y
-CONFIG_FBCON_CFB16=y
-CONFIG_FBCON_ADVANCED=y
-CONFIG_FBCON_MFB=m
-CONFIG_FBCON_CFB2=m
-CONFIG_FBCON_CFB4=m
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB24=y
-CONFIG_FBCON_CFB32=y
-CONFIG_FBCON_AFB=m
-CONFIG_FBCON_ILBM=m
-CONFIG_FBCON_IPLAN2P2=m
-CONFIG_FBCON_IPLAN2P4=m
-CONFIG_FBCON_IPLAN2P8=m
-CONFIG_FBCON_MAC=m
-CONFIG_FBCON_VGA_PLANES=m
-CONFIG_FBCON_VGA=m
-CONFIG_FBCON_HGA=m
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-CONFIG_FBCON_FONTS=y
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_SUN12x22 is not set
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-# CONFIG_FONT_ACORN_8x8 is not set
-
-#
-# Sound
-#
-CONFIG_SOUND=m
-CONFIG_SOUND_ALI5455=m
-CONFIG_SOUND_BT878=m
-CONFIG_SOUND_CMPCI=m
-CONFIG_SOUND_CMPCI_FM=y
-CONFIG_SOUND_CMPCI_FMIO=388
-CONFIG_SOUND_CMPCI_FMIO=388
-CONFIG_SOUND_CMPCI_MIDI=y
-CONFIG_SOUND_CMPCI_MPUIO=330
-CONFIG_SOUND_CMPCI_JOYSTICK=y
-CONFIG_SOUND_CMPCI_CM8738=y
-# CONFIG_SOUND_CMPCI_SPDIFINVERSE is not set
-CONFIG_SOUND_CMPCI_SPDIFLOOP=y
-CONFIG_SOUND_CMPCI_SPEAKERS=2
-CONFIG_SOUND_EMU10K1=m
-CONFIG_MIDI_EMU10K1=y
-CONFIG_SOUND_FUSION=m
-CONFIG_SOUND_CS4281=m
-CONFIG_SOUND_ES1370=m
-CONFIG_SOUND_ES1371=m
-CONFIG_SOUND_ESSSOLO1=m
-CONFIG_SOUND_MAESTRO=m
-CONFIG_SOUND_MAESTRO3=m
-CONFIG_SOUND_FORTE=m
-CONFIG_SOUND_ICH=m
-CONFIG_SOUND_RME96XX=m
-CONFIG_SOUND_SONICVIBES=m
-CONFIG_SOUND_TRIDENT=m
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-CONFIG_SOUND_VIA82CXXX=m
-CONFIG_MIDI_VIA82CXXX=y
-CONFIG_SOUND_OSS=m
-CONFIG_SOUND_TRACEINIT=y
-CONFIG_SOUND_DMAP=y
-CONFIG_SOUND_AD1816=m
-CONFIG_SOUND_AD1889=m
-CONFIG_SOUND_SGALAXY=m
-CONFIG_SOUND_ADLIB=m
-CONFIG_SOUND_ACI_MIXER=m
-CONFIG_SOUND_CS4232=m
-CONFIG_SOUND_SSCAPE=m
-CONFIG_SOUND_GUS=m
-# CONFIG_SOUND_GUS16 is not set
-CONFIG_SOUND_GUSMAX=y
-CONFIG_SOUND_VMIDI=m
-CONFIG_SOUND_TRIX=m
-CONFIG_SOUND_MSS=m
-CONFIG_SOUND_MPU401=m
-CONFIG_SOUND_NM256=m
-CONFIG_SOUND_MAD16=m
-CONFIG_MAD16_OLDCARD=y
-CONFIG_SOUND_PAS=m
-# CONFIG_PAS_JOYSTICK is not set
-CONFIG_SOUND_PSS=m
-CONFIG_PSS_MIXER=y
-# CONFIG_PSS_HAVE_BOOT is not set
-CONFIG_SOUND_SB=m
-CONFIG_SOUND_AWE32_SYNTH=m
-CONFIG_SOUND_KAHLUA=m
-CONFIG_SOUND_WAVEFRONT=m
-CONFIG_SOUND_MAUI=m
-CONFIG_SOUND_YM3812=m
-CONFIG_SOUND_OPL3SA1=m
-CONFIG_SOUND_OPL3SA2=m
-CONFIG_SOUND_YMFPCI=m
-CONFIG_SOUND_YMFPCI_LEGACY=y
-CONFIG_SOUND_UART6850=m
-CONFIG_SOUND_AEDSP16=m
-CONFIG_SC6600=y
-CONFIG_SC6600_JOY=y
-CONFIG_SC6600_CDROM=4
-CONFIG_SC6600_CDROMBASE=0
-CONFIG_AEDSP16_SBPRO=y
-CONFIG_AEDSP16_MPU401=y
-CONFIG_SOUND_TVMIXER=m
-
-#
-# Advanced Linux Sound Architecture
-#
-CONFIG_SND=m
-CONFIG_SND_BIT32_EMUL=m
-CONFIG_SND_SEQUENCER=m
-CONFIG_SND_SEQ_DUMMY=m
-CONFIG_SND_OSSEMUL=y
-CONFIG_SND_MIXER_OSS=m
-CONFIG_SND_PCM_OSS=m
-CONFIG_SND_SEQUENCER_OSS=y
-CONFIG_SND_VERBOSE_PRINTK=y
-CONFIG_SND_DEBUG=y
-CONFIG_SND_DEBUG_MEMORY=y
-# CONFIG_SND_DEBUG_DETECT is not set
-
-#
-# Generic devices
-#
-CONFIG_SND_DUMMY=m
-CONFIG_SND_VIRMIDI=m
-CONFIG_SND_MTPAV=m
-CONFIG_SND_SERIAL_U16550=m
-CONFIG_SND_MPU401=m
-CONFIG_SND_SERIALMIDI=m
-
-#
-# PCI devices
-#
-CONFIG_SND_ALI5451=m
-CONFIG_SND_CS46XX=m
-CONFIG_SND_CS46XX_NEW_DSP=y
-CONFIG_SND_CS4281=m
-CONFIG_SND_EMU10K1=m
-CONFIG_SND_PDPLUS=m
-CONFIG_SND_KORG1212=m
-CONFIG_SND_NM256=m
-CONFIG_SND_RME32=m
-CONFIG_SND_RME96=m
-CONFIG_SND_RME9652=m
-CONFIG_SND_HDSP=m
-CONFIG_SND_TRIDENT=m
-CONFIG_SND_YMFPCI=m
-CONFIG_SND_ALS4000=m
-CONFIG_SND_CMIPCI=m
-CONFIG_SND_ENS1370=m
-CONFIG_SND_ENS1371=m
-CONFIG_SND_ES1938=m
-CONFIG_SND_ES1968=m
-CONFIG_SND_MAESTRO3=m
-CONFIG_SND_FM801=m
-CONFIG_SND_ICE1712=m
-CONFIG_SND_ICE1724=m
-CONFIG_SND_INTEL8X0=m
-CONFIG_SND_SONICVIBES=m
-CONFIG_SND_VIA82XX=m
-CONFIG_SND_VX222=m
-CONFIG_SND_MIXART=m
-CONFIG_SND_AZT3328=m
-
-#
-# ALSA USB devices
-#
-CONFIG_SND_USB_AUDIO=m
-
-#
-# ALSA PCMCIA devices
-#
-CONFIG_SND_VXPOCKET=m
-CONFIG_SND_VXP440=m
-
-#
-# USB support
-#
-CONFIG_USB=m
-# CONFIG_USB_DEBUG is not set
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
-CONFIG_USB_EHCI_HCD=m
-CONFIG_USB_UHCI=m
-CONFIG_USB_UHCI_ALT=m
-CONFIG_USB_OHCI=m
-CONFIG_USB_AUDIO=m
-CONFIG_USB_EMI26=m
-CONFIG_USB_MIDI=m
-CONFIG_USB_STORAGE=m
-# CONFIG_USB_STORAGE_DEBUG is not set
-CONFIG_USB_STORAGE_DATAFAB=y
-CONFIG_USB_STORAGE_FREECOM=y
-CONFIG_USB_STORAGE_ISD200=y
-CONFIG_USB_STORAGE_DPCM=y
-CONFIG_USB_STORAGE_HP8200e=y
-CONFIG_USB_STORAGE_SDDR09=y
-CONFIG_USB_STORAGE_SDDR55=y
-CONFIG_USB_STORAGE_JUMPSHOT=y
-CONFIG_USB_ACM=m
-CONFIG_USB_PRINTER=m
-CONFIG_USB_HID=m
-CONFIG_USB_HIDINPUT=y
-CONFIG_USB_HIDDEV=y
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
-CONFIG_USB_AIPTEK=m
-CONFIG_USB_WACOM=m
-CONFIG_USB_KBTAB=m
-CONFIG_USB_POWERMATE=m
-CONFIG_USB_DC2XX=m
-CONFIG_USB_MDC800=m
-CONFIG_USB_SCANNER=m
-CONFIG_USB_MICROTEK=m
-CONFIG_USB_HPUSBSCSI=m
-CONFIG_USB_IBMCAM=m
-CONFIG_USB_KONICAWC=m
-CONFIG_USB_OV511=m
-CONFIG_USB_PWC=m
-CONFIG_USB_SE401=m
-CONFIG_USB_STV680=m
-CONFIG_USB_VICAM=m
-CONFIG_USB_DSBR=m
-CONFIG_USB_DABUSB=m
-# CONFIG_USB_LOGITECH_CAM is not set
-CONFIG_USB_PEGASUS=m
-CONFIG_USB_RTL8150=m
-CONFIG_USB_KAWETH=m
-CONFIG_USB_CATC=m
-CONFIG_USB_AX8817X=m
-CONFIG_USB_CDCETHER=m
-CONFIG_USB_USBNET=m
-CONFIG_USB_USBDNET=m
-CONFIG_USB_USBDNET_VENDOR=0000
-CONFIG_USB_USBDNET_PRODUCT=0000
-CONFIG_USB_USBDNET_CLASS=0000
-CONFIG_USB_USBDNET_SUBCLASS=0000
-CONFIG_USB_USS720=m
-
-#
-# USB Serial Converter support
-#
-CONFIG_USB_SERIAL=m
-# CONFIG_USB_SERIAL_DEBUG is not set
-CONFIG_USB_SERIAL_GENERIC=y
-CONFIG_USB_SERIAL_BELKIN=m
-CONFIG_USB_SERIAL_WHITEHEAT=m
-CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
-CONFIG_USB_SERIAL_EMPEG=m
-CONFIG_USB_SERIAL_FTDI_SIO=m
-CONFIG_USB_SERIAL_VISOR=m
-CONFIG_USB_SERIAL_IPAQ=m
-CONFIG_USB_SERIAL_IR=m
-CONFIG_USB_SERIAL_EDGEPORT=m
-CONFIG_USB_SERIAL_EDGEPORT_TI=m
-CONFIG_USB_SERIAL_KEYSPAN_PDA=m
-CONFIG_USB_SERIAL_KEYSPAN=m
-CONFIG_USB_SERIAL_KEYSPAN_USA28=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19=y
-CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
-CONFIG_USB_SERIAL_KEYSPAN_MPR=y
-CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
-CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
-CONFIG_USB_SERIAL_MCT_U232=m
-CONFIG_USB_SERIAL_KLSI=m
-CONFIG_USB_SERIAL_KOBIL_SCT=m
-CONFIG_USB_SERIAL_PL2303=m
-CONFIG_USB_SERIAL_CYBERJACK=m
-CONFIG_USB_SERIAL_XIRCOM=m
-CONFIG_USB_SERIAL_OMNINET=m
-CONFIG_USB_SERIAL_SAFE_PADDED=y
-CONFIG_USB_SAFE_SERIAL_VENDOR=0000
-CONFIG_USB_SAFE_SERIAL_PRODUCT=0000
-CONFIG_USB_RIO500=m
-CONFIG_USB_AUERSWALD=m
-CONFIG_USB_TIGL=m
-CONFIG_USB_BRLVGER=m
-CONFIG_USB_LCD=m
-# CONFIG_USB_SPEEDTOUCH is not set
-
-#
-# Bluetooth support
-#
-CONFIG_BLUEZ=m
-CONFIG_BLUEZ_L2CAP=m
-CONFIG_BLUEZ_SCO=m
-CONFIG_BLUEZ_RFCOMM=m
-CONFIG_BLUEZ_RFCOMM_TTY=y
-CONFIG_BLUEZ_BNEP=m
-CONFIG_BLUEZ_BNEP_MC_FILTER=y
-CONFIG_BLUEZ_BNEP_PROTO_FILTER=y
-CONFIG_BLUEZ_CMTP=m
-
-#
-# Bluetooth device drivers
-#
-CONFIG_BLUEZ_HCIUSB=m
-CONFIG_BLUEZ_USB_SCO=y
-# CONFIG_BLUEZ_USB_ZERO_PACKET is not set
-CONFIG_BLUEZ_HCIUART=m
-CONFIG_BLUEZ_HCIUART_H4=y
-CONFIG_BLUEZ_HCIUART_BCSP=y
-CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y
-CONFIG_BLUEZ_HCIBFUSB=m
-CONFIG_BLUEZ_HCIDTL1=m
-CONFIG_BLUEZ_HCIBT3C=m
-CONFIG_BLUEZ_HCIBLUECARD=m
-CONFIG_BLUEZ_HCIBTUART=m
-CONFIG_BLUEZ_HCIVHCI=m
-
-#
-# Kernel hacking
-#
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_CHECKING is not set
-# CONFIG_INIT_DEBUG is not set
-# CONFIG_X86_REMOTE_DEBUG is not set
-# CONFIG_IOMMU_DEBUG is not set
-# CONFIG_IOMMU_LEAK is not set
-CONFIG_DEBUG_STACKOVERFLOW=y
-CONFIG_KALLSYMS=y
-
-#
-# Library routines
-#
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_QSORT=y
-CONFIG_FW_LOADER=m
-
-#
-# Build options
-#
-CONFIG_SUSE_KERNEL=y
-CONFIG_CFGNAME="default"
-CONFIG_RELEASE=171
+++ /dev/null
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_USERMODE=y
-CONFIG_MMU=y
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-
-#
-# UML-specific options
-#
-CONFIG_MODE_TT=y
-# CONFIG_MODE_SKAS is not set
-CONFIG_NET=y
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=y
-CONFIG_HOSTFS=y
-# CONFIG_HPPFS is not set
-CONFIG_MCONSOLE=y
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_HOST_2G_2G is not set
-# CONFIG_UML_SMP is not set
-# CONFIG_SMP is not set
-CONFIG_NEST_LEVEL=0
-CONFIG_KERNEL_HALF_GIGS=1
-# CONFIG_HIGHMEM is not set
-# CONFIG_PROC_MM is not set
-CONFIG_KERNEL_STACK_ORDER=2
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# Generic Driver Options
-#
-# CONFIG_FW_LOADER is not set
-
-#
-# Character Devices
-#
-CONFIG_STDIO_CONSOLE=y
-CONFIG_SSL=y
-CONFIG_FD_CHAN=y
-# CONFIG_NULL_CHAN is not set
-CONFIG_PORT_CHAN=y
-CONFIG_PTY_CHAN=y
-CONFIG_TTY_CHAN=y
-CONFIG_XTERM_CHAN=y
-CONFIG_CON_ZERO_CHAN="fd:0,fd:1"
-CONFIG_CON_CHAN="xterm"
-CONFIG_SSL_CHAN="pty"
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-# CONFIG_WATCHDOG is not set
-# CONFIG_UML_SOUND is not set
-# CONFIG_SOUND is not set
-# CONFIG_HOSTAUDIO is not set
-
-#
-# Block Devices
-#
-CONFIG_BLK_DEV_UBD=y
-# CONFIG_BLK_DEV_UBD_SYNC is not set
-CONFIG_BLK_DEV_COW_COMMON=y
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_MMAPPER is not set
-CONFIG_NETDEVICES=y
-
-#
-# UML Network Devices
-#
-CONFIG_UML_NET=y
-CONFIG_UML_NET_ETHERTAP=y
-CONFIG_UML_NET_TUNTAP=y
-CONFIG_UML_NET_SLIP=y
-CONFIG_UML_NET_DAEMON=y
-CONFIG_UML_NET_MCAST=y
-# CONFIG_UML_NET_PCAP is not set
-# CONFIG_UML_NET_SLIRP is not set
-
-#
-# Networking support
-#
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_DUMMY=y
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=y
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-# CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-CONFIG_PPP=y
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-# CONFIG_PPP_ASYNC is not set
-# CONFIG_PPP_SYNC_TTY is not set
-# CONFIG_PPP_DEFLATE is not set
-# CONFIG_PPP_BSDCOMP is not set
-# CONFIG_PPPOE is not set
-CONFIG_SLIP=y
-# CONFIG_SLIP_COMPRESSED is not set
-# CONFIG_SLIP_SMART is not set
-# CONFIG_SLIP_MODE_SLIP6 is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-# CONFIG_NFS_FS is not set
-# CONFIG_NFSD is not set
-# CONFIG_EXPORTFS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-
-#
-# SCSI support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Kernel hacking
-#
-CONFIG_DEBUG_SLAB=y
-# CONFIG_DEBUG_SPINLOCK is not set
-CONFIG_DEBUG_INFO=y
-CONFIG_FRAME_POINTER=y
-CONFIG_PT_PROXY=y
-# CONFIG_GPROF is not set
-# CONFIG_GCOV is not set
+++ /dev/null
- Rules.make | 17 +++++++
- arch/i386/Makefile | 4 +
- arch/i386/config.in | 10 ++++
- arch/i386/vmlinux.lds | 99 -----------------------------------------
- arch/i386/vmlinux.lds.S | 99 +++++++++++++++++++++++++++++++++++++++++
- include/asm-i386/page.h | 4 +
- include/asm-i386/page_offset.h | 10 ++++
- include/asm-i386/processor.h | 4 +
- mm/memory.c | 23 +++++++--
- 9 files changed, 165 insertions(+), 105 deletions(-)
-
-Index: linux-2.4.22-vanilla/arch/i386/config.in
-===================================================================
---- linux-2.4.22-vanilla.orig/arch/i386/config.in 2003-12-02 23:55:28.000000000 +0300
-+++ linux-2.4.22-vanilla/arch/i386/config.in 2003-12-15 23:09:28.000000000 +0300
-@@ -212,6 +212,16 @@
- fi
- if [ "$CONFIG_HIGHMEM64G" = "y" ]; then
- define_bool CONFIG_X86_PAE y
-+ choice 'User address space size' \
-+ "3GB CONFIG_1GB \
-+ 2GB CONFIG_2GB \
-+ 1GB CONFIG_3GB" 3GB
-+else
-+ choice 'User address space size' \
-+ "3GB CONFIG_1GB \
-+ 2GB CONFIG_2GB \
-+ 1GB CONFIG_3GB \
-+ 3.5GB CONFIG_05GB" 3GB
- fi
-
- if [ "$CONFIG_HIGHMEM" = "y" ]; then
-Index: linux-2.4.22-vanilla/arch/i386/Makefile
-===================================================================
---- linux-2.4.22-vanilla.orig/arch/i386/Makefile 2003-11-03 22:50:58.000000000 +0300
-+++ linux-2.4.22-vanilla/arch/i386/Makefile 2003-12-15 23:09:28.000000000 +0300
-@@ -114,6 +114,9 @@
-
- MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
-
-+arch/i386/vmlinux.lds: arch/i386/vmlinux.lds.S FORCE
-+ $(CPP) -C -P -I$(HPATH) -imacros $(HPATH)/asm-i386/page_offset.h -Ui386 arch/i386/vmlinux.lds.S >arch/i386/vmlinux.lds
-+
- vmlinux: arch/i386/vmlinux.lds
-
- FORCE: ;
-@@ -150,6 +153,7 @@
- @$(MAKEBOOT) clean
-
- archmrproper:
-+ rm -f arch/i386/vmlinux.lds
-
- archdep:
- @$(MAKEBOOT) dep
-Index: linux-2.4.22-vanilla/arch/i386/vmlinux.lds.S
-===================================================================
---- linux-2.4.22-vanilla.orig/arch/i386/vmlinux.lds.S 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.22-vanilla/arch/i386/vmlinux.lds.S 2003-12-15 23:10:46.000000000 +0300
-@@ -0,0 +1,83 @@
-+/* ld script to make i386 Linux kernel
-+ * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
-+ */
-+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-+OUTPUT_ARCH(i386)
-+ENTRY(_start)
-+SECTIONS
-+{
-+ . = PAGE_OFFSET_RAW + 0x100000;
-+ _text = .; /* Text and read-only data */
-+ .text : {
-+ *(.text)
-+ *(.fixup)
-+ *(.gnu.warning)
-+ } = 0x9090
-+
-+ _etext = .; /* End of text section */
-+
-+ .rodata : { *(.rodata) *(.rodata.*) }
-+ .kstrtab : { *(.kstrtab) }
-+
-+ . = ALIGN(16); /* Exception table */
-+ __start___ex_table = .;
-+ __ex_table : { *(__ex_table) }
-+ __stop___ex_table = .;
-+
-+ __start___ksymtab = .; /* Kernel symbol table */
-+ __ksymtab : { *(__ksymtab) }
-+ __stop___ksymtab = .;
-+
-+ .data : { /* Data */
-+ *(.data)
-+ CONSTRUCTORS
-+ }
-+
-+ _edata = .; /* End of data section */
-+
-+/* chose the biggest of the possible stack sizes here? */
-+ . = ALIGN(65536); /* init_task */
-+ .data.init_task : { *(.data.init_task) }
-+
-+ . = ALIGN(4096); /* Init code and data */
-+ __init_begin = .;
-+ .text.init : { *(.text.init) }
-+ .data.init : { *(.data.init) }
-+ . = ALIGN(16);
-+ __setup_start = .;
-+ .setup.init : { *(.setup.init) }
-+ __setup_end = .;
-+ __initcall_start = .;
-+ .initcall.init : { *(.initcall.init) }
-+ __initcall_end = .;
-+ . = ALIGN(4096);
-+ __init_end = .;
-+
-+ . = ALIGN(4096);
-+ .data.page_aligned : { *(.data.idt) }
-+
-+ . = ALIGN(32);
-+ .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-+
-+ __bss_start = .; /* BSS */
-+ .bss : {
-+ *(.bss)
-+ }
-+ _end = . ;
-+
-+ /* Sections to be discarded */
-+ /DISCARD/ : {
-+ *(.text.exit)
-+ *(.data.exit)
-+ *(.exitcall.exit)
-+ }
-+
-+ /* Stabs debugging sections. */
-+ .stab 0 : { *(.stab) }
-+ .stabstr 0 : { *(.stabstr) }
-+ .stab.excl 0 : { *(.stab.excl) }
-+ .stab.exclstr 0 : { *(.stab.exclstr) }
-+ .stab.index 0 : { *(.stab.index) }
-+ .stab.indexstr 0 : { *(.stab.indexstr) }
-+ .comment 0 : { *(.comment) }
-+}
-Index: linux-2.4.22-vanilla/arch/i386/vmlinux.lds
-===================================================================
---- linux-2.4.22-vanilla.orig/arch/i386/vmlinux.lds 2003-12-15 23:17:09.000000000 +0300
-+++ linux-2.4.22-vanilla/arch/i386/vmlinux.lds 2003-01-30 13:24:37.000000000 +0300
-@@ -1,83 +0,0 @@
--/* ld script to make i386 Linux kernel
-- * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
-- */
--OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
--OUTPUT_ARCH(i386)
--ENTRY(_start)
--SECTIONS
--{
-- . = 0xC0000000 + 0x100000;
-- _text = .; /* Text and read-only data */
-- .text : {
-- *(.text)
-- *(.fixup)
-- *(.gnu.warning)
-- } = 0x9090
--
-- _etext = .; /* End of text section */
--
-- .rodata : { *(.rodata) *(.rodata.*) }
-- .kstrtab : { *(.kstrtab) }
--
-- . = ALIGN(16); /* Exception table */
-- __start___ex_table = .;
-- __ex_table : { *(__ex_table) }
-- __stop___ex_table = .;
--
-- __start___ksymtab = .; /* Kernel symbol table */
-- __ksymtab : { *(__ksymtab) }
-- __stop___ksymtab = .;
--
-- .data : { /* Data */
-- *(.data)
-- CONSTRUCTORS
-- }
--
-- _edata = .; /* End of data section */
--
--/* chose the biggest of the possible stack sizes here? */
-- . = ALIGN(65536); /* init_task */
-- .data.init_task : { *(.data.init_task) }
--
-- . = ALIGN(4096); /* Init code and data */
-- __init_begin = .;
-- .text.init : { *(.text.init) }
-- .data.init : { *(.data.init) }
-- . = ALIGN(16);
-- __setup_start = .;
-- .setup.init : { *(.setup.init) }
-- __setup_end = .;
-- __initcall_start = .;
-- .initcall.init : { *(.initcall.init) }
-- __initcall_end = .;
-- . = ALIGN(4096);
-- __init_end = .;
--
-- . = ALIGN(4096);
-- .data.page_aligned : { *(.data.idt) }
--
-- . = ALIGN(32);
-- .data.cacheline_aligned : { *(.data.cacheline_aligned) }
--
-- __bss_start = .; /* BSS */
-- .bss : {
-- *(.bss)
-- }
-- _end = . ;
--
-- /* Sections to be discarded */
-- /DISCARD/ : {
-- *(.text.exit)
-- *(.data.exit)
-- *(.exitcall.exit)
-- }
--
-- /* Stabs debugging sections. */
-- .stab 0 : { *(.stab) }
-- .stabstr 0 : { *(.stabstr) }
-- .stab.excl 0 : { *(.stab.excl) }
-- .stab.exclstr 0 : { *(.stab.exclstr) }
-- .stab.index 0 : { *(.stab.index) }
-- .stab.indexstr 0 : { *(.stab.indexstr) }
-- .comment 0 : { *(.comment) }
--}
-Index: linux-2.4.22-vanilla/include/asm-i386/page.h
-===================================================================
---- linux-2.4.22-vanilla.orig/include/asm-i386/page.h 2003-11-03 23:51:46.000000000 +0300
-+++ linux-2.4.22-vanilla/include/asm-i386/page.h 2003-12-15 23:09:28.000000000 +0300
-@@ -78,7 +78,9 @@
- * and CONFIG_HIGHMEM64G options in the kernel configuration.
- */
-
--#define __PAGE_OFFSET (0xC0000000)
-+#include <asm/page_offset.h>
-+
-+#define __PAGE_OFFSET (PAGE_OFFSET_RAW)
-
- /*
- * This much address space is reserved for vmalloc() and iomap()
-Index: linux-2.4.22-vanilla/include/asm-i386/page_offset.h
-===================================================================
---- linux-2.4.22-vanilla.orig/include/asm-i386/page_offset.h 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.22-vanilla/include/asm-i386/page_offset.h 2003-12-15 23:09:28.000000000 +0300
-@@ -0,0 +1,10 @@
-+#include <linux/config.h>
-+#ifdef CONFIG_05GB
-+#define PAGE_OFFSET_RAW 0xE0000000
-+#elif defined(CONFIG_1GB)
-+#define PAGE_OFFSET_RAW 0xC0000000
-+#elif defined(CONFIG_2GB)
-+#define PAGE_OFFSET_RAW 0x80000000
-+#elif defined(CONFIG_3GB)
-+#define PAGE_OFFSET_RAW 0x40000000
-+#endif
-Index: linux-2.4.22-vanilla/include/asm-i386/processor.h
-===================================================================
---- linux-2.4.22-vanilla.orig/include/asm-i386/processor.h 2003-12-02 23:55:28.000000000 +0300
-+++ linux-2.4.22-vanilla/include/asm-i386/processor.h 2003-12-15 23:09:28.000000000 +0300
-@@ -265,7 +265,11 @@
- /* This decides where the kernel will search for a free chunk of vm
- * space during mmap's.
- */
-+#ifndef CONFIG_05GB
- #define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-+#else
-+#define TASK_UNMAPPED_BASE (TASK_SIZE / 16)
-+#endif
-
- /*
- * Size of io_bitmap in longwords: 32 is ports 0-0x3ff.
-Index: linux-2.4.22-vanilla/mm/memory.c
-===================================================================
---- linux-2.4.22-vanilla.orig/mm/memory.c 2003-05-16 05:29:15.000000000 +0400
-+++ linux-2.4.22-vanilla/mm/memory.c 2003-12-15 23:09:28.000000000 +0300
-@@ -108,8 +108,7 @@
-
- static inline void free_one_pgd(pgd_t * dir)
- {
-- int j;
-- pmd_t * pmd;
-+ pmd_t * pmd, * md, * emd;
-
- if (pgd_none(*dir))
- return;
-@@ -120,9 +119,23 @@
- }
- pmd = pmd_offset(dir, 0);
- pgd_clear(dir);
-- for (j = 0; j < PTRS_PER_PMD ; j++) {
-- prefetchw(pmd+j+(PREFETCH_STRIDE/16));
-- free_one_pmd(pmd+j);
-+
-+ /*
-+ * Beware if changing the loop below. It once used int j,
-+ * for (j = 0; j < PTRS_PER_PMD; j++)
-+ * free_one_pmd(pmd+j);
-+ * but some older i386 compilers (e.g. egcs-2.91.66, gcc-2.95.3)
-+ * terminated the loop with a _signed_ address comparison
-+ * using "jle", when configured for HIGHMEM64GB (X86_PAE).
-+ * If also configured for 3GB of kernel virtual address space,
-+ * if page at physical 0x3ffff000 virtual 0x7ffff000 is used as
-+ * a pmd, when that mm exits the loop goes on to free "entries"
-+ * found at 0x80000000 onwards. The loop below compiles instead
-+ * to be terminated by unsigned address comparison using "jb".
-+ */
-+ for (md = pmd, emd = pmd + PTRS_PER_PMD; md < emd; md++) {
-+ prefetchw(md+(PREFETCH_STRIDE/16));
-+ free_one_pmd(md);
- }
- pmd_free(pmd);
- }
-Index: linux-2.4.22-vanilla/Rules.make
-===================================================================
---- linux-2.4.22-vanilla.orig/Rules.make 2003-05-16 05:28:27.000000000 +0400
-+++ linux-2.4.22-vanilla/Rules.make 2003-12-15 23:09:28.000000000 +0300
-@@ -215,6 +215,7 @@
- #
- # Added the SMP separator to stop module accidents between uniprocessor
- # and SMP Intel boxes - AC - from bits by Michael Chastain
-+# Added separator for different PAGE_OFFSET memory models - Ingo.
- #
-
- ifdef CONFIG_SMP
-@@ -223,6 +224,22 @@
- genksyms_smp_prefix :=
- endif
-
-+ifdef CONFIG_2GB
-+ifdef CONFIG_SMP
-+ genksyms_smp_prefix := -p smp_2gig_
-+else
-+ genksyms_smp_prefix := -p 2gig_
-+endif
-+endif
-+
-+ifdef CONFIG_3GB
-+ifdef CONFIG_SMP
-+ genksyms_smp_prefix := -p smp_3gig_
-+else
-+ genksyms_smp_prefix := -p 3gig_
-+endif
-+endif
-+
- $(MODINCL)/%.ver: %.c
- @if [ ! -r $(MODINCL)/$*.stamp -o $(MODINCL)/$*.stamp -ot $< ]; then \
- echo '$(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -E -D__GENKSYMS__ $<'; \
+++ /dev/null
-Index: linux-ia64/include/linux/mm.h
-===================================================================
---- linux-ia64.orig/include/linux/mm.h 2004-04-27 12:39:16.000000000 -0700
-+++ linux-ia64/include/linux/mm.h 2004-04-27 12:42:10.000000000 -0700
-@@ -205,6 +205,7 @@ typedef struct page {
- struct page **pprev_hash; /* Complement to *next_hash. */
- struct buffer_head * buffers; /* Buffer maps us to a disk block. */
-+ unsigned long private;
-
- /*
- * On machines where all RAM is mapped into kernel address space,
-
-_
-Index: linux-ia64/mm/filemap.c
-===================================================================
---- linux-ia64.orig/mm/filemap.c 2004-04-27 12:35:18.000000000 -0700
-+++ linux-ia64/mm/filemap.c 2004-04-27 12:42:47.000000000 -0700
-@@ -676,6 +676,7 @@ static inline void __add_to_page_cache(s
- page_cache_get(page);
- page->index = offset;
-+ page->private = 0;
- add_page_to_inode_queue(mapping, page);
- add_page_to_hash_queue(page, hash);
+++ /dev/null
-Index: kernel-2.4.21/arch/i386/kernel/entry.S
-===================================================================
---- kernel-2.4.21.orig/arch/i386/kernel/entry.S 2003-06-13 07:51:29.000000000 -0700
-+++ kernel-2.4.21/arch/i386/kernel/entry.S 2003-12-04 11:57:01.000000000 -0800
-@@ -45,6 +45,7 @@
- #include <linux/linkage.h>
- #include <asm/segment.h>
- #include <asm/smp.h>
-+#include <asm/current.h>
-
- EBX = 0x00
- ECX = 0x04
-@@ -130,10 +131,6 @@
- .long 3b,6b; \
- .previous
-
--#define GET_CURRENT(reg) \
-- movl $-8192, reg; \
-- andl %esp, reg
--
- ENTRY(lcall7)
- pushfl # We get a different stack layout with call gates,
- pushl %eax # which has to be cleaned up later..
-@@ -149,7 +146,7 @@
- movl %ecx,CS(%esp) #
- movl %esp,%ebx
- pushl %ebx
-- andl $-8192,%ebx # GET_CURRENT
-+ andl $-THREAD_SIZE,%ebx # GET_CURRENT
- movl exec_domain(%ebx),%edx # Get the execution domain
- movl 4(%edx),%edx # Get the lcall7 handler for the domain
- pushl $0x7
-@@ -173,7 +170,7 @@
- movl %ecx,CS(%esp) #
- movl %esp,%ebx
- pushl %ebx
-- andl $-8192,%ebx # GET_CURRENT
-+ andl $-THREAD_SIZE,%ebx # GET_CURRENT
- movl exec_domain(%ebx),%edx # Get the execution domain
- movl 4(%edx),%edx # Get the lcall7 handler for the domain
- pushl $0x27
-Index: kernel-2.4.21/arch/i386/kernel/smpboot.c
-===================================================================
---- kernel-2.4.21.orig/arch/i386/kernel/smpboot.c 2003-06-13 07:51:29.000000000 -0700
-+++ kernel-2.4.21/arch/i386/kernel/smpboot.c 2003-12-04 11:57:01.000000000 -0800
-@@ -819,7 +819,7 @@
-
- /* So we see what's up */
- printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip);
-- stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle);
-+ stack_start.esp = (void *)idle->thread.esp;
-
- /*
- * This grunge runs the startup process for
-@@ -892,7 +892,7 @@
- Dprintk("CPU has booted.\n");
- } else {
- boot_error= 1;
-- if (*((volatile unsigned char *)phys_to_virt(8192))
-+ if (*((volatile unsigned char *)phys_to_virt(THREAD_SIZE))
- == 0xA5)
- /* trampoline started but...? */
- printk("Stuck ??\n");
-@@ -915,7 +915,7 @@
- }
-
- /* mark "stuck" area as not stuck */
-- *((volatile unsigned long *)phys_to_virt(8192)) = 0;
-+ *((volatile unsigned long *)phys_to_virt(THREAD_SIZE)) = 0;
-
- if(clustered_apic_mode == CLUSTERED_APIC_NUMAQ) {
- printk("Restoring NMI vector\n");
-Index: kernel-2.4.21/arch/i386/kernel/traps.c
-===================================================================
---- kernel-2.4.21.orig/arch/i386/kernel/traps.c 2002-11-28 15:53:09.000000000 -0800
-+++ kernel-2.4.21/arch/i386/kernel/traps.c 2003-12-04 11:57:01.000000000 -0800
-@@ -158,7 +158,7 @@
- unsigned long esp = tsk->thread.esp;
-
- /* User space on another CPU? */
-- if ((esp ^ (unsigned long)tsk) & (PAGE_MASK<<1))
-+ if ((esp ^ (unsigned long)tsk) & ~(THREAD_SIZE - 1))
- return;
- show_trace((unsigned long *)esp);
- }
-Index: kernel-2.4.21/arch/i386/kernel/head.S
-===================================================================
---- kernel-2.4.21.orig/arch/i386/kernel/head.S 2003-06-13 07:51:29.000000000 -0700
-+++ kernel-2.4.21/arch/i386/kernel/head.S 2003-12-04 11:57:01.000000000 -0800
-@@ -15,6 +15,7 @@
- #include <asm/page.h>
- #include <asm/pgtable.h>
- #include <asm/desc.h>
-+#include <asm/current.h>
-
- #define OLD_CL_MAGIC_ADDR 0x90020
- #define OLD_CL_MAGIC 0xA33F
-@@ -320,7 +321,7 @@
- ret
-
- ENTRY(stack_start)
-- .long SYMBOL_NAME(init_task_union)+8192
-+ .long SYMBOL_NAME(init_task_union)+THREAD_SIZE
- .long __KERNEL_DS
-
- /* This is the default interrupt "handler" :-) */
-Index: kernel-2.4.21/arch/i386/kernel/irq.c
-===================================================================
---- kernel-2.4.21.orig/arch/i386/kernel/irq.c 2002-11-28 15:53:09.000000000 -0800
-+++ kernel-2.4.21/arch/i386/kernel/irq.c 2003-12-04 11:57:01.000000000 -0800
-@@ -581,7 +581,10 @@
- long esp;
-
- /* Debugging check for stack overflow: is there less than 1KB free? */
-- __asm__ __volatile__("andl %%esp,%0" : "=r" (esp) : "0" (8191));
-+ __asm__ __volatile__(
-+ "andl %%esp,%0"
-+ : "=r" (esp) : "0" (THREAD_SIZE-1));
-+
- if (unlikely(esp < (sizeof(struct task_struct) + 1024))) {
- extern void show_stack(unsigned long *);
-
-Index: kernel-2.4.21/arch/i386/lib/getuser.S
-===================================================================
---- kernel-2.4.21.orig/arch/i386/lib/getuser.S 1998-01-12 13:42:52.000000000 -0800
-+++ kernel-2.4.21/arch/i386/lib/getuser.S 2003-12-04 11:57:01.000000000 -0800
-@@ -21,6 +21,10 @@
- * as they get called from within inline assembly.
- */
-
-+/* Duplicated from asm/processor.h */
-+#include <asm/current.h>
-+#include <linux/config.h>
-+
- addr_limit = 12
-
- .text
-@@ -28,7 +32,7 @@
- .globl __get_user_1
- __get_user_1:
- movl %esp,%edx
-- andl $0xffffe000,%edx
-+ andl $~(THREAD_SIZE - 1),%edx
- cmpl addr_limit(%edx),%eax
- jae bad_get_user
- 1: movzbl (%eax),%edx
-@@ -41,7 +45,7 @@
- addl $1,%eax
- movl %esp,%edx
- jc bad_get_user
-- andl $0xffffe000,%edx
-+ andl $~(THREAD_SIZE - 1),%edx
- cmpl addr_limit(%edx),%eax
- jae bad_get_user
- 2: movzwl -1(%eax),%edx
-@@ -54,7 +58,7 @@
- addl $3,%eax
- movl %esp,%edx
- jc bad_get_user
-- andl $0xffffe000,%edx
-+ andl $~(THREAD_SIZE - 1),%edx
- cmpl addr_limit(%edx),%eax
- jae bad_get_user
- 3: movl -3(%eax),%edx
-Index: kernel-2.4.21/arch/i386/config.in
-===================================================================
---- kernel-2.4.21.orig/arch/i386/config.in 2003-06-13 07:51:29.000000000 -0700
-+++ kernel-2.4.21/arch/i386/config.in 2003-12-04 11:57:01.000000000 -0800
-@@ -256,6 +256,29 @@
- if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then
- define_bool CONFIG_HAVE_DEC_LOCK y
- fi
-+
-+choice 'Bigger Stack Size Support' \
-+ "off CONFIG_NOBIGSTACK \
-+ 16KB CONFIG_STACK_SIZE_16KB \
-+ 32KB CONFIG_STACK_SIZE_32KB \
-+ 64KB CONFIG_STACK_SIZE_64KB" off
-+
-+if [ "$CONFIG_NOBIGSTACK" = "y" ]; then
-+ define_int CONFIG_STACK_SIZE_SHIFT 1
-+else
-+ if [ "$CONFIG_STACK_SIZE_16KB" = "y" ]; then
-+ define_int CONFIG_STACK_SIZE_SHIFT 2
-+ else
-+ if [ "$CONFIG_STACK_SIZE_32KB" = "y" ]; then
-+ define_int CONFIG_STACK_SIZE_SHIFT 3
-+ else
-+ if [ "$CONFIG_STACK_SIZE_64KB" = "y" ]; then
-+ define_int CONFIG_STACK_SIZE_SHIFT 4
-+ fi
-+ fi
-+ fi
-+fi
-+
- endmenu
-
- mainmenu_option next_comment
-Index: kernel-2.4.21/arch/i386/vmlinux.lds
-===================================================================
---- kernel-2.4.21.orig/arch/i386/vmlinux.lds 2002-02-25 11:37:53.000000000 -0800
-+++ kernel-2.4.21/arch/i386/vmlinux.lds 2003-12-04 11:57:01.000000000 -0800
-@@ -35,7 +35,8 @@
-
- _edata = .; /* End of data section */
-
-- . = ALIGN(8192); /* init_task */
-+/* chose the biggest of the possible stack sizes here? */
-+ . = ALIGN(65536); /* init_task */
- .data.init_task : { *(.data.init_task) }
-
- . = ALIGN(4096); /* Init code and data */
-Index: kernel-2.4.21/include/asm-i386/current.h
-===================================================================
---- kernel-2.4.21.orig/include/asm-i386/current.h 1998-08-14 16:35:22.000000000 -0700
-+++ kernel-2.4.21/include/asm-i386/current.h 2003-12-04 11:57:01.000000000 -0800
-@@ -1,15 +1,43 @@
- #ifndef _I386_CURRENT_H
- #define _I386_CURRENT_H
-+#include <asm/page.h>
-+
-+/*
-+ * Configurable page sizes on i386, mainly for debugging purposes.
-+ * (c) Balbir Singh
-+ */
-+
-+#ifdef __ASSEMBLY__
-+
-+#define PAGE_SIZE 4096 /* as cannot handle 1UL << 12 */
-+#define THREAD_SIZE ((1 << CONFIG_STACK_SIZE_SHIFT) * PAGE_SIZE)
-+
-+#define GET_CURRENT(reg) \
-+ movl $-THREAD_SIZE, reg; \
-+ andl %esp, reg
-+
-+#else /* __ASSEMBLY__ */
-+
-+#define THREAD_SIZE ((1 << CONFIG_STACK_SIZE_SHIFT) * PAGE_SIZE)
-+#define alloc_task_struct() \
-+ ((struct task_struct *) __get_free_pages(GFP_KERNEL,CONFIG_STACK_SIZE_SHIFT))
-+
-+#define free_task_struct(p) \
-+ free_pages((unsigned long) (p), CONFIG_STACK_SIZE_SHIFT)
-+
-+#define INIT_TASK_SIZE THREAD_SIZE
-
- struct task_struct;
-
- static inline struct task_struct * get_current(void)
- {
- struct task_struct *current;
-- __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL));
-+ __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~(THREAD_SIZE - 1)));
- return current;
- }
-
- #define current get_current()
-
-+#endif /* __ASSEMBLY__ */
-+
- #endif /* !(_I386_CURRENT_H) */
-Index: kernel-2.4.21/include/asm-i386/hw_irq.h
-===================================================================
---- kernel-2.4.21.orig/include/asm-i386/hw_irq.h 2001-11-22 11:46:18.000000000 -0800
-+++ kernel-2.4.21/include/asm-i386/hw_irq.h 2003-12-04 11:57:01.000000000 -0800
-@@ -15,6 +15,7 @@
- #include <linux/config.h>
- #include <asm/atomic.h>
- #include <asm/irq.h>
-+#include <asm/current.h>
-
- /*
- * IDT vectors usable for external interrupt sources start
-@@ -113,10 +114,6 @@
- #define IRQ_NAME2(nr) nr##_interrupt(void)
- #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
-
--#define GET_CURRENT \
-- "movl %esp, %ebx\n\t" \
-- "andl $-8192, %ebx\n\t"
--
- /*
- * SMP has a few special interrupts for IPI messages
- */
-Index: kernel-2.4.21/include/asm-i386/processor.h
-===================================================================
---- kernel-2.4.21.orig/include/asm-i386/processor.h 2003-06-13 07:51:38.000000000 -0700
-+++ kernel-2.4.21/include/asm-i386/processor.h 2003-12-04 11:57:01.000000000 -0800
-@@ -14,6 +14,7 @@
- #include <asm/types.h>
- #include <asm/sigcontext.h>
- #include <asm/cpufeature.h>
-+#include <asm/current.h>
- #include <linux/cache.h>
- #include <linux/config.h>
- #include <linux/threads.h>
-@@ -453,9 +454,6 @@
- #define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019])
- #define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
-
--#define THREAD_SIZE (2*PAGE_SIZE)
--#define alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
--#define free_task_struct(p) free_pages((unsigned long) (p), 1)
- #define get_task_struct(tsk) atomic_inc(&virt_to_page(tsk)->count)
-
- #define init_task (init_task_union.task)
-Index: kernel-2.4.21/include/linux/sched.h
-===================================================================
---- kernel-2.4.21.orig/include/linux/sched.h 2003-06-13 15:26:52.000000000 -0700
-+++ kernel-2.4.21/include/linux/sched.h 2003-12-04 12:00:14.000000000 -0800
-@@ -2,6 +2,7 @@
- #define _LINUX_SCHED_H
-
- #include <asm/param.h> /* for HZ */
-+#include <asm/current.h> /* maybe for INIT_TASK_SIZE */
-
- extern unsigned long event;
-
-Index: kernel-2.4.21/include/asm-x86_64/current.h
-===================================================================
---- kernel-2.4.21.orig/include/asm-x86_64/current.h 2003-06-13 15:26:52.000000000 -0700
-+++ kernel-2.4.21/include/asm-x86_64/current.h 2003-12-04 12:00:13.000000000 -0800
-@@ -5,6 +5,7 @@
- struct task_struct;
-
- #include <asm/pda.h>
-+#include <asm/page.h>
-
- static inline struct task_struct *get_current(void)
- {
+++ /dev/null
-Index: linux-2.4.20-rh/drivers/block/blkpg.c
-===================================================================
---- linux-2.4.20-rh.orig/drivers/block/blkpg.c 2003-07-22 16:02:29.000000000 +0800
-+++ linux-2.4.20-rh/drivers/block/blkpg.c 2003-12-09 17:33:09.000000000 +0800
-@@ -297,3 +297,38 @@
- }
-
- EXPORT_SYMBOL(blk_ioctl);
-+
-+#define NUM_DEV_NO_WRITE 16
-+static int dev_no_write[NUM_DEV_NO_WRITE];
-+
-+/*
-+ * Debug code for turning block devices "read-only" (will discard writes
-+ * silently). This is for filesystem crash/recovery testing.
-+ */
-+void dev_set_rdonly(kdev_t dev, int no_write)
-+{
-+ if (dev) {
-+ printk(KERN_WARNING "Turning device %s read-only\n",
-+ bdevname(dev));
-+ dev_no_write[no_write] = 0xdead0000 + dev;
-+ }
-+}
-+
-+int dev_check_rdonly(kdev_t dev) {
-+ int i;
-+
-+ for (i = 0; i < NUM_DEV_NO_WRITE; i++) {
-+ if ((dev_no_write[i] & 0xffff0000) == 0xdead0000 &&
-+ dev == (dev_no_write[i] & 0xffff))
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+void dev_clear_rdonly(int no_write) {
-+ dev_no_write[no_write] = 0;
-+}
-+
-+EXPORT_SYMBOL(dev_set_rdonly);
-+EXPORT_SYMBOL(dev_check_rdonly);
-+EXPORT_SYMBOL(dev_clear_rdonly);
-Index: linux-2.4.20-rh/drivers/block/ll_rw_blk.c
-===================================================================
---- linux-2.4.20-rh.orig/drivers/block/ll_rw_blk.c 2003-07-22 16:02:34.000000000 +0800
-+++ linux-2.4.20-rh/drivers/block/ll_rw_blk.c 2003-12-09 17:39:38.000000000 +0800
-@@ -1183,6 +1183,10 @@
- buffer_IO_error(bh);
- break;
- }
-+ if ((rw & WRITE)&&(dev_check_rdonly(bh->b_rdev))) {
-+ bh->b_end_io(bh, 0);
-+ break;
-+ }
- } while (q->make_request_fn(q, rw, bh));
- }
-
+++ /dev/null
-Index: lum/mm/filemap.c
-===================================================================
---- lum.orig/mm/filemap.c 2004-04-25 14:58:10.000000000 -0400
-+++ lum/mm/filemap.c 2004-04-25 16:23:32.000000000 -0400
-@@ -1614,8 +1614,8 @@
- new_iobuf = 1;
- }
-
-- blocksize = 1 << inode->i_blkbits;
-- blocksize_bits = inode->i_blkbits;
-+ blocksize = 512 /*1 << inode->i_blkbits*/;
-+ blocksize_bits = 9 /*inode->i_blkbits*/;
- blocksize_mask = blocksize - 1;
- chunk_size = KIO_MAX_ATOMIC_IO << 10;
-
+++ /dev/null
- arch/i386/kernel/crash.c | 24 +++++++++++++++++-------
- arch/i386/kernel/nmi.c | 2 +-
- include/asm-i386/apic.h | 1 +
- include/linux/crash.h | 2 +-
- kernel/bootimg.c | 13 ++++++++++++-
- kernel/bootimg_pic.c | 6 ++++--
- 6 files changed, 36 insertions(+), 12 deletions(-)
-
-Index: linux-2.4.20-rh/kernel/bootimg.c
-===================================================================
---- linux-2.4.20-rh.orig/kernel/bootimg.c 2003-10-29 23:56:02.000000000 +0800
-+++ linux-2.4.20-rh/kernel/bootimg.c 2003-10-29 23:56:17.000000000 +0800
-@@ -238,9 +238,20 @@
- int error = -ENOMEM;
-
- if (bootimg_checksum(__va(bootimg_dsc.page_dir),bootimg_dsc.pages)
-- != bootimg_dsc.csum)
-+ != bootimg_dsc.csum) {
- printk("Checksum of kernel image failed. Rebooting via BIOS\n");
-
-+ /* Before calling machine_restart(), make sure it will not
-+ * simply call this function recursively.
-+ */
-+ bootimg_dsc.page_dir = NULL;
-+ machine_restart(NULL);
-+
-+ /* We should never get here, but just in case... */
-+ for (; ; )
-+ __asm__ __volatile__ ("hlt");
-+ }
-+
- code_page = get_identity_mapped_page();
- if (!code_page) goto out3;
- code = (relocate_and_jump_t) virt_to_phys((void *) code_page);
-Index: linux-2.4.20-rh/kernel/bootimg_pic.c
-===================================================================
---- linux-2.4.20-rh.orig/kernel/bootimg_pic.c 2003-10-29 23:56:02.000000000 +0800
-+++ linux-2.4.20-rh/kernel/bootimg_pic.c 2003-10-29 23:56:17.000000000 +0800
-@@ -69,7 +69,8 @@
- for (j = i+1; j < dsc.pages; j++) {
- table = dsc.page_dir+FROM_TABLE(j);
- if (((unsigned long) *table) == to) {
-- copy_and_swap(*table,dsc.scratch);
-+ copy_and_swap((unsigned long) (*table),
-+ dsc.scratch);
- break;
- }
- if ((*table)[PAGE_NR(j)] == to) {
-@@ -79,7 +80,8 @@
- }
- table = dsc.page_dir+TO_TABLE(j);
- if (((unsigned long) *table) == to) {
-- copy_and_swap(*table,dsc.scratch);
-+ copy_and_swap((unsigned long) (*table),
-+ dsc.scratch);
- break;
- }
- }
-Index: linux-2.4.20-rh/include/asm-i386/apic.h
-===================================================================
---- linux-2.4.20-rh.orig/include/asm-i386/apic.h 2003-10-29 23:58:49.000000000 +0800
-+++ linux-2.4.20-rh/include/asm-i386/apic.h 2003-10-29 23:59:40.000000000 +0800
-@@ -86,6 +86,9 @@
- extern void apic_pm_unregister(struct pm_dev*);
-
- extern int check_nmi_watchdog (void);
-+extern void disable_apic_nmi_watchdog(void);
-+
-+
-
- extern unsigned int nmi_watchdog;
- #define NMI_NONE 0
-Index: linux-2.4.20-rh/include/linux/crash.h
-===================================================================
---- linux-2.4.20-rh.orig/include/linux/crash.h 2003-10-29 23:56:02.000000000 +0800
-+++ linux-2.4.20-rh/include/linux/crash.h 2003-10-29 23:56:17.000000000 +0800
-@@ -71,7 +71,7 @@
- #define CRASH_ZALLOC_PAGES 16*5*2 /* 2 to handle crash in crash */
- #define CRASH_LOW_WATER_PAGES 100
-
--#define CRASH_CPU_TIMEOUT 5000 /* 5 sec wait for other cpus to stop */
-+#define CRASH_CPU_TIMEOUT 15000 /* 15 sec wait for other cpus to stop */
-
- #define CRASH_MARK_RESERVED(addr) (set_bit(PG_reserved,&mem_map[MAP_NR(addr)].flags))
- #define CRASH_CLEAR_RESERVED(addr) (clear_bit(PG_reserved,&mem_map[MAP_NR(addr)].flags))
-Index: linux-2.4.20-rh/arch/i386/kernel/crash.c
-===================================================================
---- linux-2.4.20-rh.orig/arch/i386/kernel/crash.c 2003-10-29 23:56:02.000000000 +0800
-+++ linux-2.4.20-rh/arch/i386/kernel/crash.c 2003-10-29 23:56:17.000000000 +0800
-@@ -9,6 +9,8 @@
- #include <linux/crash.h>
- #include <linux/reboot.h>
- #include <linux/bootimg.h>
-+#include <asm/fixmap.h>
-+#include <asm/apic.h>
-
- inline void crash_save_regs(void) {
- static unsigned long regs[8];
-@@ -30,15 +32,23 @@
- */
- void crash_save_current_state(struct task_struct *tp)
- {
-+ if (tp != NULL) {
-+ /*
-+ * Here we save ebp instead of esp just in case the compiler
-+ * decides to put an extra push in before we execute this
-+ * instruction (thus invalidating our frame pointer).
-+ */
-+ asm volatile("movl %%ebp,%0":"=m" (*(u_long *)&tp->thread.esp));
-+ tp->thread.eip = (u_long)crash_save_current_state;
-+ panic_ksp[smp_processor_id()] = tp->thread.esp;
-+ mb();
-+ }
-+
- /*
-- * Here we save ebp instead of esp just in case the compiler
-- * decides to put an extra push in before we execute this
-- * instruction (thus invalidating our frame pointer).
-+ * Just to be safe, disable the NMI watchdog on the calling CPU so it
-+ * doesn't get in the way while we are trying to save a dump.
- */
-- asm volatile("movl %%ebp,%0":"=m" (*(u_long *)&tp->thread.esp));
-- tp->thread.eip = (u_long)crash_save_current_state;
-- panic_ksp[smp_processor_id()] = tp->thread.esp;
-- mb();
-+ disable_apic_nmi_watchdog();
-
- save_core();
-
-Index: linux-2.4.20-rh/arch/i386/kernel/nmi.c
-===================================================================
---- linux-2.4.20-rh.orig/arch/i386/kernel/nmi.c 2003-10-29 23:56:02.000000000 +0800
-+++ linux-2.4.20-rh/arch/i386/kernel/nmi.c 2003-10-29 23:56:17.000000000 +0800
-@@ -138,7 +138,7 @@
-
- struct pm_dev *nmi_pmdev;
-
--static void disable_apic_nmi_watchdog(void)
-+void disable_apic_nmi_watchdog(void)
- {
- switch (boot_cpu_data.x86_vendor) {
- case X86_VENDOR_AMD:
+++ /dev/null
- include/linux/dynlocks.h | 33 ++++++++++
- lib/Makefile | 4 -
- lib/dynlocks.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 187 insertions(+), 2 deletions(-)
-
-Index: linux-2.4.24/include/linux/dynlocks.h
-===================================================================
---- linux-2.4.24.orig/include/linux/dynlocks.h 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.24/include/linux/dynlocks.h 2004-07-18 11:09:33.000000000 +0400
-@@ -0,0 +1,43 @@
-+#ifndef _LINUX_DYNLOCKS_H
-+#define _LINUX_DYNLOCKS_H
-+
-+#include <linux/list.h>
-+#include <linux/wait.h>
-+
-+#define DYNLOCK_MAGIC 0xd19a10c
-+#define DYNLOCK_MAGIC2 0xd1956ee
-+
-+struct dynlock;
-+
-+struct dynlock_member {
-+ unsigned dl_magic;
-+ struct list_head dl_list;
-+ unsigned long dl_value; /* lock value */
-+ int dl_refcount; /* number of users */
-+ int dl_readers;
-+ int dl_writers;
-+ int dl_pid; /* holder of the lock */
-+ wait_queue_head_t dl_wait;
-+};
-+
-+/*
-+ * lock's namespace:
-+ * - list of locks
-+ * - lock to protect this list
-+ */
-+
-+#define DYNLOCK_LIST_MAGIC 0x11ee91e6
-+
-+struct dynlock {
-+ unsigned dl_magic;
-+ struct list_head dl_list;
-+ spinlock_t dl_list_lock;
-+};
-+
-+void dynlock_init(struct dynlock *dl);
-+void *dynlock_lock(struct dynlock *dl, unsigned long value, int rw, int gfp);
-+void dynlock_unlock(struct dynlock *dl, void *lock);
-+
-+
-+#endif
-+
-Index: linux-2.4.24/lib/dynlocks.c
-===================================================================
---- linux-2.4.24.orig/lib/dynlocks.c 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.24/lib/dynlocks.c 2004-07-18 11:23:01.000000000 +0400
-@@ -0,0 +1,188 @@
-+/*
-+ * Dynamic Locks
-+ *
-+ * struct dynlock is lockspace
-+ * one may request lock (exclusive or shared) for some value
-+ * in that lockspace
-+ *
-+ */
-+
-+#include <linux/dynlocks.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/init.h>
-+
-+static kmem_cache_t * dynlock_cachep = NULL;
-+
-+void __init dynlock_cache_init(void)
-+{
-+ printk(KERN_INFO "init dynlocks cache\n");
-+ dynlock_cachep = kmem_cache_create("dynlock_cache",
-+ sizeof(struct dynlock_member),
-+ 0,
-+ SLAB_HWCACHE_ALIGN,
-+ NULL, NULL);
-+ if (dynlock_cachep == NULL)
-+ panic("Can't create dynlock cache");
-+}
-+
-+/*
-+ * dynlock_init
-+ *
-+ * initialize lockspace
-+ *
-+ */
-+void dynlock_init(struct dynlock *dl)
-+{
-+ spin_lock_init(&dl->dl_list_lock);
-+ INIT_LIST_HEAD(&dl->dl_list);
-+ dl->dl_magic = DYNLOCK_LIST_MAGIC;
-+}
-+
-+/*
-+ * dynlock_lock
-+ *
-+ * acquires lock (exclusive or shared) in specified lockspace
-+ * each lock in lockspace is allocated separately, so user have
-+ * to specify GFP flags.
-+ * routine returns pointer to lock. this pointer is intended to
-+ * be passed to dynlock_unlock
-+ *
-+ */
-+void *dynlock_lock(struct dynlock *dl, unsigned long value, int rw, int gfp)
-+{
-+ struct dynlock_member *nhl = NULL;
-+ struct dynlock_member *hl;
-+ struct list_head *cur;
-+ int num = 0;
-+
-+ BUG_ON(dl == NULL);
-+ BUG_ON(dl->dl_magic != DYNLOCK_LIST_MAGIC);
-+repeat:
-+ /* find requested lock in lockspace */
-+ spin_lock(&dl->dl_list_lock);
-+ BUG_ON(dl->dl_list.next == NULL);
-+ BUG_ON(dl->dl_list.prev == NULL);
-+ list_for_each(cur, &dl->dl_list) {
-+ BUG_ON(cur->next == NULL);
-+ BUG_ON(cur->prev == NULL);
-+ hl = list_entry(cur, struct dynlock_member, dl_list);
-+ BUG_ON(hl->dl_magic != DYNLOCK_MAGIC);
-+ if (hl->dl_value == value) {
-+ /* lock is found */
-+ if (nhl) {
-+ /* someone else just allocated
-+ * lock we didn't find and just created
-+ * so, we drop our lock
-+ */
-+ kmem_cache_free(dynlock_cachep, nhl);
-+ nhl = NULL;
-+ }
-+ hl->dl_refcount++;
-+ goto found;
-+ }
-+ num++;
-+ }
-+ /* lock not found */
-+ if (nhl) {
-+ /* we already have allocated lock. use it */
-+ hl = nhl;
-+ nhl = NULL;
-+ list_add(&hl->dl_list, &dl->dl_list);
-+ goto found;
-+ }
-+ spin_unlock(&dl->dl_list_lock);
-+
-+ /* lock not found and we haven't allocated lock yet. allocate it */
-+ nhl = kmem_cache_alloc(dynlock_cachep, gfp);
-+ if (nhl == NULL)
-+ return NULL;
-+ nhl->dl_refcount = 1;
-+ nhl->dl_value = value;
-+ nhl->dl_readers = 0;
-+ nhl->dl_writers = 0;
-+ nhl->dl_magic = DYNLOCK_MAGIC;
-+ init_waitqueue_head(&nhl->dl_wait);
-+
-+ /* while lock is being allocated, someone else may allocate it
-+ * and put onto to list. check this situation
-+ */
-+ goto repeat;
-+
-+found:
-+ if (rw) {
-+ /* exclusive lock: user don't want to share lock at all
-+ * NOTE: one process may take the same lock several times
-+ * this functionaly is useful for rename operations */
-+ while ((hl->dl_writers && hl->dl_pid != current->pid) ||
-+ hl->dl_readers) {
-+ spin_unlock(&dl->dl_list_lock);
-+ wait_event(hl->dl_wait,
-+ hl->dl_writers == 0 && hl->dl_readers == 0);
-+ spin_lock(&dl->dl_list_lock);
-+ }
-+ hl->dl_writers++;
-+ } else {
-+ /* shared lock: user do not want to share lock with writer */
-+ while (hl->dl_writers) {
-+ spin_unlock(&dl->dl_list_lock);
-+ wait_event(hl->dl_wait, hl->dl_writers == 0);
-+ spin_lock(&dl->dl_list_lock);
-+ }
-+ hl->dl_readers++;
-+ }
-+ hl->dl_pid = current->pid;
-+ spin_unlock(&dl->dl_list_lock);
-+
-+ return hl;
-+}
-+
-+
-+/*
-+ * dynlock_unlock
-+ *
-+ * user have to specify lockspace (dl) and pointer to lock structure
-+ * returned by dynlock_lock()
-+ *
-+ */
-+void dynlock_unlock(struct dynlock *dl, void *lock)
-+{
-+ struct dynlock_member *hl = lock;
-+ int wakeup = 0;
-+
-+ BUG_ON(dl == NULL);
-+ BUG_ON(hl == NULL);
-+ BUG_ON(dl->dl_magic != DYNLOCK_LIST_MAGIC);
-+ BUG_ON(hl->dl_magic != DYNLOCK_MAGIC);
-+ BUG_ON(current->pid != hl->dl_pid);
-+
-+ spin_lock(&dl->dl_list_lock);
-+ if (hl->dl_writers) {
-+ BUG_ON(hl->dl_readers > 0 || hl->dl_readers < 0);
-+ hl->dl_writers--;
-+ if (hl->dl_writers == 0)
-+ wakeup = 1;
-+ } else if (hl->dl_readers) {
-+ hl->dl_readers--;
-+ if (hl->dl_readers == 0)
-+ wakeup = 1;
-+ } else {
-+ BUG_ON(1);
-+ }
-+ if (wakeup) {
-+ hl->dl_pid = 0;
-+ wake_up(&hl->dl_wait);
-+ }
-+ if (--(hl->dl_refcount) == 0) {
-+ hl->dl_magic = DYNLOCK_MAGIC2;
-+ list_del(&hl->dl_list);
-+ kmem_cache_free(dynlock_cachep, hl);
-+ }
-+ spin_unlock(&dl->dl_list_lock);
-+}
-+
-+EXPORT_SYMBOL(dynlock_init);
-+EXPORT_SYMBOL(dynlock_lock);
-+EXPORT_SYMBOL(dynlock_unlock);
-+
-Index: linux-2.4.24/lib/Makefile
-===================================================================
---- linux-2.4.24.orig/lib/Makefile 2004-06-24 09:06:32.000000000 +0400
-+++ linux-2.4.24/lib/Makefile 2004-07-16 15:54:06.000000000 +0400
-@@ -9,10 +9,10 @@
- L_TARGET := lib.a
-
- export-objs := cmdline.o dec_and_lock.o rwsem-spinlock.o rwsem.o \
-- rbtree.o crc32.o firmware_class.o
-+ rbtree.o crc32.o firmware_class.o dynlocks.o
-
- obj-y := errno.o ctype.o string.o vsprintf.o brlock.o cmdline.o \
-- bust_spinlocks.o rbtree.o dump_stack.o
-+ bust_spinlocks.o rbtree.o dump_stack.o dynlocks.o
-
- obj-$(CONFIG_FW_LOADER) += firmware_class.o
- obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
-Index: linux-2.4.24/fs/dcache.c
-===================================================================
---- linux-2.4.24.orig/fs/dcache.c 2004-07-16 12:35:54.000000000 +0400
-+++ linux-2.4.24/fs/dcache.c 2004-07-16 15:54:06.000000000 +0400
-@@ -1274,6 +1274,7 @@
- extern void bdev_cache_init(void);
- extern void cdev_cache_init(void);
- extern void iobuf_cache_init(void);
-+extern void dynlock_cache_init(void);
-
- void __init vfs_caches_init(unsigned long mempages)
- {
-@@ -1310,4 +1311,5 @@
- bdev_cache_init();
- cdev_cache_init();
- iobuf_cache_init();
-+ dynlock_cache_init();
- }
+++ /dev/null
- mm/filemap.c | 2 ++
- 1 files changed, 2 insertions(+)
-
---- linux-2.4.20-l19/mm/filemap.c~export-add_to_page_cache 2003-07-15 03:05:47.000000000 -0500
-+++ linux-2.4.20-l19-zab/mm/filemap.c 2003-07-15 15:33:01.000000000 -0500
-@@ -670,6 +670,7 @@ void add_to_page_cache(struct page * pag
- spin_unlock(&pagecache_lock);
- lru_cache_add(page);
- }
-+EXPORT_SYMBOL_GPL(add_to_page_cache);
-
- int add_to_page_cache_unique(struct page * page,
- struct address_space *mapping, unsigned long offset,
-@@ -692,6 +693,7 @@ int add_to_page_cache_unique(struct page
- lru_cache_add(page);
- return err;
- }
-+EXPORT_SYMBOL_GPL(add_to_page_cache_unique);
-
- /*
- * This adds the requested page to the page cache if it isn't already there,
-
-_
+++ /dev/null
- include/linux/mm.h | 1 +
- mm/filemap.c | 3 ++-
- 2 files changed, 3 insertions(+), 1 deletion(-)
-
---- linux-2.4.18-18/include/linux/mm.h~export-truncate 2003-04-05 02:54:55.000000000 -0700
-+++ linux-2.4.18-18-braam/include/linux/mm.h 2003-04-09 17:37:46.000000000 -0600
-@@ -650,6 +650,7 @@ struct zone_t;
- /* filemap.c */
- extern void remove_inode_page(struct page *);
- extern unsigned long page_unuse(struct page *);
-+extern void truncate_complete_page(struct page *);
- extern void truncate_inode_pages(struct address_space *, loff_t);
-
- /* generic vm_area_ops exported for stackable file systems */
---- linux-2.4.18-18/mm/filemap.c~export-truncate 2003-04-05 02:54:55.000000000 -0700
-+++ linux-2.4.18-18-braam/mm/filemap.c 2003-04-09 17:37:46.000000000 -0600
-@@ -245,7 +245,7 @@ static inline void truncate_partial_page
- do_flushpage(page, partial);
- }
-
--static void truncate_complete_page(struct page *page)
-+void truncate_complete_page(struct page *page)
- {
- /*
- * Leave it on the LRU if it gets converted into anonymous buffers
-@@ -266,6 +266,7 @@ static void truncate_complete_page(struc
- remove_inode_page(page);
- page_cache_release(page);
- }
-+EXPORT_SYMBOL_GPL(truncate_complete_page);
-
- static int FASTCALL(truncate_list_pages(struct list_head *, unsigned long, unsigned *));
- static int truncate_list_pages(struct list_head *head, unsigned long start, unsigned *partial)
-
-_
+++ /dev/null
-Index: linux-2.4.24-l36mmap/mm/memory.c
-===================================================================
---- linux-2.4.24-l36mmap.orig/mm/memory.c 2004-05-27 17:44:13.000000000 -0700
-+++ linux-2.4.24-l36mmap/mm/memory.c 2004-05-27 17:45:07.000000000 -0700
-@@ -411,6 +411,7 @@
- mm->rss = 0;
- spin_unlock(&mm->page_table_lock);
- }
-+EXPORT_SYMBOL_GPL(zap_page_range);
-
- /*
- * Do a quick page-table lookup for a single page.
+++ /dev/null
-diff -rupN linux-2.4.24/fs/namei.c linux-2.4.24.new/fs/namei.c
---- linux-2.4.24/fs/namei.c 2004-05-19 10:58:50.000000000 +0300
-+++ linux-2.4.24.new/fs/namei.c 2004-05-19 11:04:05.725450928 +0300
-@@ -1391,8 +1391,8 @@ int open_namei(const char *pathname, int
-
-
- /* SMP-safe */
--static struct dentry *lookup_create(struct nameidata *nd, int is_dir,
-- struct lookup_intent *it)
-+struct dentry *lookup_create(struct nameidata *nd, int is_dir,
-+ struct lookup_intent *it)
- {
- struct dentry *dentry;
-
-@@ -1412,6 +1412,7 @@ enoent:
- fail:
- return dentry;
- }
-+EXPORT_SYMBOL(lookup_create);
-
- int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
- {
-diff -rupN linux-2.4.24/include/linux/fs.h linux-2.4.24.new/include/linux/fs.h
---- linux-2.4.24/include/linux/fs.h 2004-05-19 10:58:50.178421368 +0300
-+++ linux-2.4.24.new/include/linux/fs.h 2004-05-19 11:04:35.373943672 +0300
-@@ -1129,6 +1129,8 @@ extern struct file *filp_open(const char
- extern struct file * dentry_open(struct dentry *, struct vfsmount *, int);
- extern int open_namei_it(const char *filename, int namei_flags, int mode,
- struct nameidata *nd, struct lookup_intent *it);
-+extern struct dentry *lookup_create(struct nameidata *nd, int is_dir,
-+ struct lookup_intent *it);
- extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
- int flags, struct lookup_intent *it);
- extern int revalidate_it(struct dentry *dentry, struct lookup_intent *it);
+++ /dev/null
---- linux/arch/i386/kernel/i386_ksyms.c.orig 2003-11-28 11:26:19.000000000 -0700
-+++ linux/arch/i386/kernel/i386_ksyms.c 2004-08-13 11:31:33.000000000 -0600
-@@ -131,6 +131,7 @@
- EXPORT_SYMBOL(cpu_data);
- EXPORT_SYMBOL(kernel_flag_cacheline);
- EXPORT_SYMBOL(smp_num_cpus);
-+EXPORT_SYMBOL(smp_num_siblings);
- EXPORT_SYMBOL(cpu_online_map);
- EXPORT_SYMBOL_NOVERS(__write_lock_failed);
- EXPORT_SYMBOL_NOVERS(__read_lock_failed);
+++ /dev/null
- fs/ext3/Makefile | 2 ++
- fs/ext3/super.c | 2 +-
- include/linux/fs.h | 1 +
- kernel/ksyms.c | 4 ++++
- 4 files changed, 8 insertions(+), 1 deletion(-)
-
---- linux/fs/ext3/Makefile~exports_2.4.20 Wed Apr 9 10:07:14 2003
-+++ linux-mmonroe/fs/ext3/Makefile Wed Apr 9 10:19:53 2003
-@@ -9,6 +9,8 @@
-
- O_TARGET := ext3.o
-
-+export-objs := super.o inode.o
-+
- obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
- ioctl.o namei.o super.o symlink.o
- obj-m := $(O_TARGET)
---- linux/fs/ext3/super.c~exports_2.4.20 Wed Apr 9 10:07:14 2003
-+++ linux-mmonroe/fs/ext3/super.c Wed Apr 9 10:19:53 2003
-@@ -1769,7 +1769,7 @@ static void __exit exit_ext3_fs(void)
- unregister_filesystem(&ext3_fs_type);
- }
-
--EXPORT_NO_SYMBOLS;
-+EXPORT_SYMBOL(ext3_bread);
-
- MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
- MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
---- linux/include/linux/fs.h~exports_2.4.20 Wed Apr 9 10:07:14 2003
-+++ linux-mmonroe/include/linux/fs.h Wed Apr 9 10:19:53 2003
-@@ -1020,6 +1020,7 @@ extern int unregister_filesystem(struct
- extern struct vfsmount *kern_mount(struct file_system_type *);
- extern int may_umount(struct vfsmount *);
- extern long do_mount(char *, char *, char *, unsigned long, void *);
-+struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
-
- #define kern_umount mntput
-
---- linux/kernel/ksyms.c~exports_2.4.20 Wed Apr 9 10:07:14 2003
-+++ linux-mmonroe/kernel/ksyms.c Wed Apr 9 10:19:53 2003
-@@ -308,6 +308,10 @@ EXPORT_SYMBOL(dcache_dir_fsync);
- EXPORT_SYMBOL(dcache_readdir);
- EXPORT_SYMBOL(dcache_dir_ops);
-
-+/* lustre */
-+EXPORT_SYMBOL(pagecache_lock_cacheline);
-+EXPORT_SYMBOL(do_kern_mount);
-+
- /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */
- EXPORT_SYMBOL(default_llseek);
- EXPORT_SYMBOL(dentry_open);
-
-_
+++ /dev/null
- fs/ext3/ialloc.c | 20 ++++++++++----------
- fs/ext3/namei.c | 16 ++++++++--------
- include/linux/ext3_fs.h | 2 +-
- 3 files changed, 19 insertions(+), 19 deletions(-)
-
---- linux-2.4.20/fs/ext3/ialloc.c~ext3-2.4-ino_t 2003-04-08 23:35:24.000000000 -0600
-+++ linux-2.4.20-braam/fs/ext3/ialloc.c 2003-04-08 23:35:24.000000000 -0600
-@@ -65,8 +65,8 @@ static int read_inode_bitmap (struct sup
- if (!bh) {
- ext3_error (sb, "read_inode_bitmap",
- "Cannot read inode bitmap - "
-- "block_group = %lu, inode_bitmap = %lu",
-- block_group, (unsigned long) gdp->bg_inode_bitmap);
-+ "block_group = %lu, inode_bitmap = %u",
-+ block_group, gdp->bg_inode_bitmap);
- retval = -EIO;
- }
- /*
-@@ -533,19 +533,19 @@ out:
- }
-
- /* Verify that we are loading a valid orphan from disk */
--struct inode *ext3_orphan_get (struct super_block * sb, ino_t ino)
-+struct inode *ext3_orphan_get(struct super_block *sb, unsigned long ino)
- {
-- ino_t max_ino = le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count);
-+ unsigned long max_ino = le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count);
- unsigned long block_group;
- int bit;
- int bitmap_nr;
- struct buffer_head *bh;
- struct inode *inode = NULL;
--
-+
- /* Error cases - e2fsck has already cleaned up for us */
- if (ino > max_ino) {
- ext3_warning(sb, __FUNCTION__,
-- "bad orphan ino %ld! e2fsck was run?\n", ino);
-+ "bad orphan ino %lu! e2fsck was run?\n", ino);
- return NULL;
- }
-
-@@ -554,7 +554,7 @@ struct inode *ext3_orphan_get (struct su
- if ((bitmap_nr = load_inode_bitmap(sb, block_group)) < 0 ||
- !(bh = EXT3_SB(sb)->s_inode_bitmap[bitmap_nr])) {
- ext3_warning(sb, __FUNCTION__,
-- "inode bitmap error for orphan %ld\n", ino);
-+ "inode bitmap error for orphan %lu\n", ino);
- return NULL;
- }
-
-@@ -565,16 +565,16 @@ struct inode *ext3_orphan_get (struct su
- if (!ext3_test_bit(bit, bh->b_data) || !(inode = iget(sb, ino)) ||
- is_bad_inode(inode) || NEXT_ORPHAN(inode) > max_ino) {
- ext3_warning(sb, __FUNCTION__,
-- "bad orphan inode %ld! e2fsck was run?\n", ino);
-+ "bad orphan inode %lu! e2fsck was run?\n", ino);
- printk(KERN_NOTICE "ext3_test_bit(bit=%d, block=%ld) = %d\n",
- bit, bh->b_blocknr, ext3_test_bit(bit, bh->b_data));
- printk(KERN_NOTICE "inode=%p\n", inode);
- if (inode) {
- printk(KERN_NOTICE "is_bad_inode(inode)=%d\n",
- is_bad_inode(inode));
-- printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%d\n",
-+ printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n",
- NEXT_ORPHAN(inode));
-- printk(KERN_NOTICE "max_ino=%ld\n", max_ino);
-+ printk(KERN_NOTICE "max_ino=%lu\n", max_ino);
- }
- /* Avoid freeing blocks if we got a bad deleted inode */
- if (inode && inode->i_nlink == 0)
---- linux-2.4.20/fs/ext3/namei.c~ext3-2.4-ino_t 2003-04-08 23:35:24.000000000 -0600
-+++ linux-2.4.20-braam/fs/ext3/namei.c 2003-04-08 23:35:24.000000000 -0600
-@@ -1808,10 +1808,10 @@ int ext3_orphan_del(handle_t *handle, st
- struct list_head *prev;
- struct ext3_inode_info *ei = EXT3_I(inode);
- struct ext3_sb_info *sbi;
-- ino_t ino_next;
-+ unsigned long ino_next;
- struct ext3_iloc iloc;
- int err = 0;
--
-+
- lock_super(inode->i_sb);
- if (list_empty(&ei->i_orphan)) {
- unlock_super(inode->i_sb);
-@@ -1822,7 +1822,7 @@ int ext3_orphan_del(handle_t *handle, st
- prev = ei->i_orphan.prev;
- sbi = EXT3_SB(inode->i_sb);
-
-- jbd_debug(4, "remove inode %ld from orphan list\n", inode->i_ino);
-+ jbd_debug(4, "remove inode %lu from orphan list\n", inode->i_ino);
-
- list_del(&ei->i_orphan);
- INIT_LIST_HEAD(&ei->i_orphan);
-@@ -1833,13 +1833,13 @@ int ext3_orphan_del(handle_t *handle, st
- * list in memory. */
- if (!handle)
- goto out;
--
-+
- err = ext3_reserve_inode_write(handle, inode, &iloc);
- if (err)
- goto out_err;
-
- if (prev == &sbi->s_orphan) {
-- jbd_debug(4, "superblock will point to %ld\n", ino_next);
-+ jbd_debug(4, "superblock will point to %lu\n", ino_next);
- BUFFER_TRACE(sbi->s_sbh, "get_write_access");
- err = ext3_journal_get_write_access(handle, sbi->s_sbh);
- if (err)
-@@ -1850,8 +1850,8 @@ int ext3_orphan_del(handle_t *handle, st
- struct ext3_iloc iloc2;
- struct inode *i_prev =
- list_entry(prev, struct inode, u.ext3_i.i_orphan);
--
-- jbd_debug(4, "orphan inode %ld will point to %ld\n",
-+
-+ jbd_debug(4, "orphan inode %lu will point to %lu\n",
- i_prev->i_ino, ino_next);
- err = ext3_reserve_inode_write(handle, i_prev, &iloc2);
- if (err)
-@@ -1866,7 +1866,7 @@ int ext3_orphan_del(handle_t *handle, st
- if (err)
- goto out_brelse;
-
--out_err:
-+out_err:
- ext3_std_error(inode->i_sb, err);
- out:
- unlock_super(inode->i_sb);
---- linux-2.4.20/include/linux/ext3_fs.h~ext3-2.4-ino_t 2003-04-08 23:35:24.000000000 -0600
-+++ linux-2.4.20-braam/include/linux/ext3_fs.h 2003-04-08 23:35:24.000000000 -0600
-@@ -673,7 +673,7 @@ extern int ext3fs_dirhash(const char *na
- /* ialloc.c */
- extern struct inode * ext3_new_inode (handle_t *, const struct inode *, int);
- extern void ext3_free_inode (handle_t *, struct inode *);
--extern struct inode * ext3_orphan_get (struct super_block *, ino_t);
-+extern struct inode * ext3_orphan_get (struct super_block *, unsigned long);
- extern unsigned long ext3_count_free_inodes (struct super_block *);
- extern void ext3_check_inodes_bitmap (struct super_block *);
- extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
-
-_
+++ /dev/null
- fs/ext3/file.c | 4
- fs/ext3/inode.c | 116 ++++++++++++++++++++++
- fs/ext3/super.c | 230 +++++++++++++++++++++++++++++++++++++++++++++
- include/linux/ext3_fs.h | 5
- include/linux/ext3_fs_sb.h | 10 +
- 5 files changed, 365 insertions(+)
-
-Index: linux-2.4.24/fs/ext3/super.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/super.c 2004-01-12 20:36:31.000000000 +0300
-+++ linux-2.4.24/fs/ext3/super.c 2004-01-13 16:27:43.000000000 +0300
-@@ -400,6 +400,128 @@
- }
- }
-
-+#ifdef EXT3_DELETE_THREAD
-+/*
-+ * Delete inodes in a loop until there are no more to be deleted.
-+ * Normally, we run in the background doing the deletes and sleeping again,
-+ * and clients just add new inodes to be deleted onto the end of the list.
-+ * If someone is concerned about free space (e.g. block allocation or similar)
-+ * then they can sleep on s_delete_waiter_queue and be woken up when space
-+ * has been freed.
-+ */
-+int ext3_delete_thread(void *data)
-+{
-+ struct super_block *sb = data;
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+ struct task_struct *tsk = current;
-+ struct inode *inode;
-+ unsigned long blocks;
-+
-+ /* Almost like daemonize, but not quite */
-+ exit_mm(current);
-+ tsk->session = 1;
-+ tsk->pgrp = 1;
-+ tsk->tty = NULL;
-+ exit_files(current);
-+ reparent_to_init();
-+
-+ sprintf(tsk->comm, "kdelext3-%s", kdevname(sb->s_dev));
-+ sigfillset(&tsk->blocked);
-+
-+ /*tsk->flags |= PF_KERNTHREAD;*/
-+
-+ INIT_LIST_HEAD(&sbi->s_delete_list);
-+ wake_up(&sbi->s_delete_waiter_queue);
-+ ext3_debug("delete thread on %s started\n", kdevname(sb->s_dev));
-+
-+ /* main loop */
-+ for (;;) {
-+ wait_event_interruptible(sbi->s_delete_thread_queue,
-+ !list_empty(&sbi->s_delete_list) ||
-+ !test_opt(sb, ASYNCDEL));
-+ ext3_debug("%s woken up: %lu inodes, %lu blocks\n",
-+ tsk->comm,sbi->s_delete_inodes,sbi->s_delete_blocks);
-+
-+ spin_lock(&sbi->s_delete_lock);
-+ if (list_empty(&sbi->s_delete_list)) {
-+ clear_opt(sbi->s_mount_opt, ASYNCDEL);
-+ memset(&sbi->s_delete_list, 0,
-+ sizeof(sbi->s_delete_list));
-+ spin_unlock(&sbi->s_delete_lock);
-+ ext3_debug("delete thread on %s exiting\n",
-+ kdevname(sb->s_dev));
-+ wake_up(&sbi->s_delete_waiter_queue);
-+ break;
-+ }
-+
-+ while (!list_empty(&sbi->s_delete_list)) {
-+ inode = list_entry(sbi->s_delete_list.next,
-+ struct inode, i_devices);
-+ blocks = inode->i_blocks >> (inode->i_blkbits - 9);
-+
-+ list_del_init(&inode->i_devices);
-+ spin_unlock(&sbi->s_delete_lock);
-+ ext3_debug("%s delete ino %lu blk %lu\n",
-+ tsk->comm, inode->i_ino, blocks);
-+
-+ J_ASSERT(EXT3_I(inode)->i_state & EXT3_STATE_DELETE);
-+ J_ASSERT(inode->i_nlink == 1);
-+ inode->i_nlink = 0;
-+ iput(inode);
-+
-+ spin_lock(&sbi->s_delete_lock);
-+ sbi->s_delete_blocks -= blocks;
-+ sbi->s_delete_inodes--;
-+ }
-+ if (sbi->s_delete_blocks != 0 || sbi->s_delete_inodes != 0) {
-+ ext3_warning(sb, __FUNCTION__,
-+ "%lu blocks, %lu inodes on list?\n",
-+ sbi->s_delete_blocks,sbi->s_delete_inodes);
-+ sbi->s_delete_blocks = 0;
-+ sbi->s_delete_inodes = 0;
-+ }
-+ spin_unlock(&sbi->s_delete_lock);
-+ wake_up(&sbi->s_delete_waiter_queue);
-+ }
-+
-+ return 0;
-+}
-+
-+static void ext3_start_delete_thread(struct super_block *sb)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+ int rc;
-+
-+ spin_lock_init(&sbi->s_delete_lock);
-+ init_waitqueue_head(&sbi->s_delete_thread_queue);
-+ init_waitqueue_head(&sbi->s_delete_waiter_queue);
-+
-+ if (!test_opt(sb, ASYNCDEL))
-+ return;
-+
-+ rc = kernel_thread(ext3_delete_thread, sb, CLONE_VM | CLONE_FILES);
-+ if (rc < 0)
-+ printk(KERN_ERR "EXT3-fs: cannot start delete thread: rc %d\n",
-+ rc);
-+ else
-+ wait_event(sbi->s_delete_waiter_queue, sbi->s_delete_list.next);
-+}
-+
-+static void ext3_stop_delete_thread(struct ext3_sb_info *sbi)
-+{
-+ if (sbi->s_delete_list.next == 0) /* thread never started */
-+ return;
-+
-+ clear_opt(sbi->s_mount_opt, ASYNCDEL);
-+ wake_up(&sbi->s_delete_thread_queue);
-+ wait_event(sbi->s_delete_waiter_queue,
-+ sbi->s_delete_list.next == 0 && sbi->s_delete_inodes == 0);
-+}
-+#else
-+#define ext3_start_delete_thread(sbi) do {} while(0)
-+#define ext3_stop_delete_thread(sbi) do {} while(0)
-+#endif /* EXT3_DELETE_THREAD */
-+
- void ext3_put_super (struct super_block * sb)
- {
- struct ext3_sb_info *sbi = EXT3_SB(sb);
-@@ -407,6 +529,7 @@
- kdev_t j_dev = sbi->s_journal->j_dev;
- int i;
-
-+ J_ASSERT(sbi->s_delete_inodes == 0);
- ext3_xattr_put_super(sb);
- journal_destroy(sbi->s_journal);
- if (!(sb->s_flags & MS_RDONLY)) {
-@@ -527,6 +650,13 @@
- clear_opt (*mount_options, XATTR_USER);
- else
- #endif
-+#ifdef EXT3_DELETE_THREAD
-+ if (!strcmp(this_char, "asyncdel"))
-+ set_opt(*mount_options, ASYNCDEL);
-+ else if (!strcmp(this_char, "noasyncdel"))
-+ clear_opt(*mount_options, ASYNCDEL);
-+ else
-+#endif
- if (!strcmp (this_char, "bsddf"))
- clear_opt (*mount_options, MINIX_DF);
- else if (!strcmp (this_char, "nouid32")) {
-@@ -1227,6 +1357,7 @@
- }
-
- ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY);
-+ ext3_start_delete_thread(sb);
- /*
- * akpm: core read_super() calls in here with the superblock locked.
- * That deadlocks, because orphan cleanup needs to lock the superblock
-@@ -1618,7 +1749,12 @@
- static int ext3_sync_fs(struct super_block *sb)
- {
- tid_t target;
--
-+
-+ if (atomic_read(&sb->s_active) == 0) {
-+ /* fs is being umounted: time to stop delete thread */
-+ ext3_stop_delete_thread(EXT3_SB(sb));
-+ }
-+
- sb->s_dirt = 0;
- target = log_start_commit(EXT3_SB(sb)->s_journal, NULL);
- log_wait_commit(EXT3_SB(sb)->s_journal, target);
-@@ -1682,6 +1818,9 @@
- if (!parse_options(data, &tmp, sbi, &tmp, 1))
- return -EINVAL;
-
-+ if (!test_opt(sb, ASYNCDEL) || (*flags & MS_RDONLY))
-+ ext3_stop_delete_thread(sbi);
-+
- if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
- ext3_abort(sb, __FUNCTION__, "Abort forced by user");
-
-Index: linux-2.4.24/fs/ext3/inode.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/inode.c 2004-01-12 20:36:31.000000000 +0300
-+++ linux-2.4.24/fs/ext3/inode.c 2004-01-12 20:36:32.000000000 +0300
-@@ -2551,6 +2551,118 @@
- return err;
- }
-
-+#ifdef EXT3_DELETE_THREAD
-+/* Move blocks from to-be-truncated inode over to a new inode, and delete
-+ * that one from the delete thread instead. This avoids a lot of latency
-+ * when truncating large files.
-+ *
-+ * If we have any problem deferring the truncate, just truncate it right away.
-+ * If we defer it, we also mark how many blocks it would free, so that we
-+ * can keep the statfs data correct, and we know if we should sleep on the
-+ * delete thread when we run out of space.
-+ */
-+void ext3_truncate_thread(struct inode *old_inode)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(old_inode->i_sb);
-+ struct ext3_inode_info *nei, *oei = EXT3_I(old_inode);
-+ struct inode *new_inode;
-+ handle_t *handle;
-+ unsigned long blocks = old_inode->i_blocks >> (old_inode->i_blkbits-9);
-+
-+ if (!test_opt(old_inode->i_sb, ASYNCDEL) || !sbi->s_delete_list.next)
-+ goto out_truncate;
-+
-+ /* XXX This is a temporary limitation for code simplicity.
-+ * We could truncate to arbitrary sizes at some later time.
-+ */
-+ if (old_inode->i_size != 0)
-+ goto out_truncate;
-+
-+ /* We may want to truncate the inode immediately and not defer it */
-+ if (IS_SYNC(old_inode) || blocks <= EXT3_NDIR_BLOCKS ||
-+ old_inode->i_size > oei->i_disksize)
-+ goto out_truncate;
-+
-+ /* We can't use the delete thread as-is during real orphan recovery,
-+ * as we add to the orphan list here, causing ext3_orphan_cleanup()
-+ * to loop endlessly. It would be nice to do so, but needs work.
-+ */
-+ if (oei->i_state & EXT3_STATE_DELETE ||
-+ sbi->s_mount_state & EXT3_ORPHAN_FS) {
-+ ext3_debug("doing deferred inode %lu delete (%lu blocks)\n",
-+ old_inode->i_ino, blocks);
-+ goto out_truncate;
-+ }
-+
-+ ext3_discard_prealloc(old_inode);
-+
-+ /* old_inode = 1
-+ * new_inode = sb + GDT + ibitmap
-+ * orphan list = 1 inode/superblock for add, 2 inodes for del
-+ * quota files = 2 * EXT3_SINGLEDATA_TRANS_BLOCKS
-+ */
-+ handle = ext3_journal_start(old_inode, 7);
-+ if (IS_ERR(handle))
-+ goto out_truncate;
-+
-+ new_inode = ext3_new_inode(handle, old_inode, old_inode->i_mode);
-+ if (IS_ERR(new_inode)) {
-+ ext3_debug("truncate inode %lu directly (no new inodes)\n",
-+ old_inode->i_ino);
-+ goto out_journal;
-+ }
-+
-+ nei = EXT3_I(new_inode);
-+
-+ down_write(&oei->truncate_sem);
-+ new_inode->i_size = old_inode->i_size;
-+ new_inode->i_blocks = old_inode->i_blocks;
-+ new_inode->i_uid = old_inode->i_uid;
-+ new_inode->i_gid = old_inode->i_gid;
-+ new_inode->i_nlink = 1;
-+
-+ /* FIXME when we do arbitrary truncates */
-+ old_inode->i_blocks = oei->i_file_acl ? old_inode->i_blksize / 512 : 0;
-+ old_inode->i_mtime = old_inode->i_ctime = CURRENT_TIME;
-+
-+ memcpy(nei->i_data, oei->i_data, sizeof(nei->i_data));
-+ memset(oei->i_data, 0, sizeof(oei->i_data));
-+
-+ nei->i_disksize = oei->i_disksize;
-+ nei->i_state |= EXT3_STATE_DELETE;
-+ up_write(&oei->truncate_sem);
-+
-+ if (ext3_orphan_add(handle, new_inode) < 0)
-+ goto out_journal;
-+
-+ if (ext3_orphan_del(handle, old_inode) < 0) {
-+ ext3_orphan_del(handle, new_inode);
-+ iput(new_inode);
-+ goto out_journal;
-+ }
-+
-+ ext3_journal_stop(handle, old_inode);
-+
-+ spin_lock(&sbi->s_delete_lock);
-+ J_ASSERT(list_empty(&new_inode->i_devices));
-+ list_add_tail(&new_inode->i_devices, &sbi->s_delete_list);
-+ sbi->s_delete_blocks += blocks;
-+ sbi->s_delete_inodes++;
-+ spin_unlock(&sbi->s_delete_lock);
-+
-+ ext3_debug("delete inode %lu (%lu blocks) by thread\n",
-+ new_inode->i_ino, blocks);
-+
-+ wake_up(&sbi->s_delete_thread_queue);
-+ return;
-+
-+out_journal:
-+ ext3_journal_stop(handle, old_inode);
-+out_truncate:
-+ ext3_truncate(old_inode);
-+}
-+#endif /* EXT3_DELETE_THREAD */
-+
- /*
- * On success, We end up with an outstanding reference count against
- * iloc->bh. This _must_ be cleaned up later.
-Index: linux-2.4.24/fs/ext3/file.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/file.c 2004-01-12 20:36:29.000000000 +0300
-+++ linux-2.4.24/fs/ext3/file.c 2004-01-12 20:36:32.000000000 +0300
-@@ -126,7 +126,11 @@
- };
-
- struct inode_operations ext3_file_inode_operations = {
-+#ifdef EXT3_DELETE_THREAD
-+ truncate: ext3_truncate_thread, /* BKL held */
-+#else
- truncate: ext3_truncate, /* BKL held */
-+#endif
- setattr: ext3_setattr, /* BKL held */
- setxattr: ext3_setxattr, /* BKL held */
- getxattr: ext3_getxattr, /* BKL held */
-Index: linux-2.4.24/fs/ext3/namei.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/namei.c 2004-01-12 20:36:31.000000000 +0300
-+++ linux-2.4.24/fs/ext3/namei.c 2004-01-12 20:36:32.000000000 +0300
-@@ -1936,6 +1936,36 @@
- return retval;
- }
-
-+static int ext3_try_to_delay_deletion(struct inode *inode)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(inode->i_sb);
-+ struct ext3_inode_info *ei = EXT3_I(inode);
-+ unsigned long blocks;
-+
-+ if (!test_opt(inode->i_sb, ASYNCDEL))
-+ return 0;
-+
-+ /* We may want to delete the inode immediately and not defer it */
-+ blocks = inode->i_blocks >> (inode->i_blkbits - 9);
-+ if (IS_SYNC(inode) || blocks <= EXT3_NDIR_BLOCKS)
-+ return 0;
-+
-+ inode->i_nlink = 1;
-+ atomic_inc(&inode->i_count);
-+ ei->i_state |= EXT3_STATE_DELETE;
-+
-+ spin_lock(&sbi->s_delete_lock);
-+ J_ASSERT(list_empty(&inode->i_devices));
-+ list_add_tail(&inode->i_devices, &sbi->s_delete_list);
-+ sbi->s_delete_blocks += blocks;
-+ sbi->s_delete_inodes++;
-+ spin_unlock(&sbi->s_delete_lock);
-+
-+ wake_up(&sbi->s_delete_thread_queue);
-+
-+ return 0;
-+}
-+
- static int ext3_unlink(struct inode * dir, struct dentry *dentry)
- {
- int retval;
-@@ -1977,8 +2007,10 @@
- ext3_update_dx_flag(dir);
- ext3_mark_inode_dirty(handle, dir);
- inode->i_nlink--;
-- if (!inode->i_nlink)
-+ if (!inode->i_nlink) {
-+ ext3_try_to_delay_deletion(inode);
- ext3_orphan_add(handle, inode);
-+ }
- inode->i_ctime = dir->i_ctime;
- ext3_mark_inode_dirty(handle, inode);
- retval = 0;
-Index: linux-2.4.24/include/linux/ext3_fs.h
-===================================================================
---- linux-2.4.24.orig/include/linux/ext3_fs.h 2004-01-12 20:36:31.000000000 +0300
-+++ linux-2.4.24/include/linux/ext3_fs.h 2004-01-12 20:36:32.000000000 +0300
-@@ -193,6 +193,7 @@
- */
- #define EXT3_STATE_JDATA 0x00000001 /* journaled data exists */
- #define EXT3_STATE_NEW 0x00000002 /* inode is newly created */
-+#define EXT3_STATE_DELETE 0x00000010 /* deferred delete inode */
-
- /*
- * ioctl commands
-@@ -320,6 +321,7 @@
- #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */
- #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */
- #define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
-+#define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */
-
- /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
- #ifndef _LINUX_EXT2_FS_H
-@@ -697,6 +699,9 @@
- extern void ext3_dirty_inode(struct inode *);
- extern int ext3_change_inode_journal_flag(struct inode *, int);
- extern void ext3_truncate (struct inode *);
-+#ifdef EXT3_DELETE_THREAD
-+extern void ext3_truncate_thread(struct inode *inode);
-+#endif
- extern void ext3_set_inode_flags(struct inode *);
-
- /* ioctl.c */
-Index: linux-2.4.24/include/linux/ext3_fs_sb.h
-===================================================================
---- linux-2.4.24.orig/include/linux/ext3_fs_sb.h 2004-01-12 20:36:31.000000000 +0300
-+++ linux-2.4.24/include/linux/ext3_fs_sb.h 2004-01-12 20:36:32.000000000 +0300
-@@ -29,6 +29,8 @@
-
- #define EXT3_MAX_GROUP_LOADED 8
-
-+#define EXT3_DELETE_THREAD
-+
- /*
- * third extended-fs super-block data in memory
- */
-@@ -76,6 +78,14 @@
- struct timer_list turn_ro_timer; /* For turning read-only (crash simulation) */
- wait_queue_head_t ro_wait_queue; /* For people waiting for the fs to go read-only */
- #endif
-+#ifdef EXT3_DELETE_THREAD
-+ spinlock_t s_delete_lock;
-+ struct list_head s_delete_list;
-+ unsigned long s_delete_blocks;
-+ unsigned long s_delete_inodes;
-+ wait_queue_head_t s_delete_thread_queue;
-+ wait_queue_head_t s_delete_waiter_queue;
-+#endif
- };
-
- #endif /* _LINUX_EXT3_FS_SB */
+++ /dev/null
- fs/ext3/file.c | 4
- fs/ext3/inode.c | 116 ++++++++++++++++++++++
- fs/ext3/super.c | 230 +++++++++++++++++++++++++++++++++++++++++++++
- include/linux/ext3_fs.h | 5
- include/linux/ext3_fs_sb.h | 10 +
- 5 files changed, 365 insertions(+)
-
-Index: linux-2.4.21-suse/fs/ext3/super.c
-===================================================================
---- linux-2.4.21-suse.orig/fs/ext3/super.c 2004-01-12 19:49:25.000000000 +0300
-+++ linux-2.4.21-suse/fs/ext3/super.c 2004-01-13 17:39:59.000000000 +0300
-@@ -400,6 +400,221 @@
- }
- }
-
-+#ifdef EXT3_DELETE_THREAD
-+/*
-+ * Delete inodes in a loop until there are no more to be deleted.
-+ * Normally, we run in the background doing the deletes and sleeping again,
-+ * and clients just add new inodes to be deleted onto the end of the list.
-+ * If someone is concerned about free space (e.g. block allocation or similar)
-+ * then they can sleep on s_delete_waiter_queue and be woken up when space
-+ * has been freed.
-+ */
-+int ext3_delete_thread(void *data)
-+{
-+ struct super_block *sb = data;
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+ struct task_struct *tsk = current;
-+
-+ /* Almost like daemonize, but not quite */
-+ exit_mm(current);
-+ tsk->session = 1;
-+ tsk->pgrp = 1;
-+ tsk->tty = NULL;
-+ exit_files(current);
-+ reparent_to_init();
-+
-+ sprintf(tsk->comm, "kdelext3-%s", kdevname(sb->s_dev));
-+ sigfillset(&tsk->blocked);
-+
-+ /*tsk->flags |= PF_KERNTHREAD;*/
-+
-+ INIT_LIST_HEAD(&sbi->s_delete_list);
-+ wake_up(&sbi->s_delete_waiter_queue);
-+ ext3_debug("delete thread on %s started\n", kdevname(sb->s_dev));
-+
-+ /* main loop */
-+ for (;;) {
-+ wait_event_interruptible(sbi->s_delete_thread_queue,
-+ !list_empty(&sbi->s_delete_list) ||
-+ !test_opt(sb, ASYNCDEL));
-+ ext3_debug("%s woken up: %lu inodes, %lu blocks\n",
-+ tsk->comm,sbi->s_delete_inodes,sbi->s_delete_blocks);
-+
-+ spin_lock(&sbi->s_delete_lock);
-+ if (list_empty(&sbi->s_delete_list)) {
-+ clear_opt(sbi->s_mount_opt, ASYNCDEL);
-+ memset(&sbi->s_delete_list, 0,
-+ sizeof(sbi->s_delete_list));
-+ spin_unlock(&sbi->s_delete_lock);
-+ ext3_debug("delete thread on %s exiting\n",
-+ kdevname(sb->s_dev));
-+ wake_up(&sbi->s_delete_waiter_queue);
-+ break;
-+ }
-+
-+ while (!list_empty(&sbi->s_delete_list)) {
-+ struct inode *inode=list_entry(sbi->s_delete_list.next,
-+ struct inode, i_dentry);
-+ unsigned long blocks = inode->i_blocks >>
-+ (inode->i_blkbits - 9);
-+
-+ list_del_init(&inode->i_dentry);
-+ spin_unlock(&sbi->s_delete_lock);
-+ ext3_debug("%s delete ino %lu blk %lu\n",
-+ tsk->comm, inode->i_ino, blocks);
-+
-+ iput(inode);
-+
-+ spin_lock(&sbi->s_delete_lock);
-+ sbi->s_delete_blocks -= blocks;
-+ sbi->s_delete_inodes--;
-+ }
-+ if (sbi->s_delete_blocks != 0 || sbi->s_delete_inodes != 0) {
-+ ext3_warning(sb, __FUNCTION__,
-+ "%lu blocks, %lu inodes on list?\n",
-+ sbi->s_delete_blocks,sbi->s_delete_inodes);
-+ sbi->s_delete_blocks = 0;
-+ sbi->s_delete_inodes = 0;
-+ }
-+ spin_unlock(&sbi->s_delete_lock);
-+ wake_up(&sbi->s_delete_waiter_queue);
-+ }
-+
-+ return 0;
-+}
-+
-+static void ext3_start_delete_thread(struct super_block *sb)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+ int rc;
-+
-+ spin_lock_init(&sbi->s_delete_lock);
-+ init_waitqueue_head(&sbi->s_delete_thread_queue);
-+ init_waitqueue_head(&sbi->s_delete_waiter_queue);
-+
-+ if (!test_opt(sb, ASYNCDEL))
-+ return;
-+
-+ rc = kernel_thread(ext3_delete_thread, sb, CLONE_VM | CLONE_FILES);
-+ if (rc < 0)
-+ printk(KERN_ERR "EXT3-fs: cannot start delete thread: rc %d\n",
-+ rc);
-+ else
-+ wait_event(sbi->s_delete_waiter_queue, sbi->s_delete_list.next);
-+}
-+
-+static void ext3_stop_delete_thread(struct ext3_sb_info *sbi)
-+{
-+ if (sbi->s_delete_list.next == 0) /* thread never started */
-+ return;
-+
-+ clear_opt(sbi->s_mount_opt, ASYNCDEL);
-+ wake_up(&sbi->s_delete_thread_queue);
-+ wait_event(sbi->s_delete_waiter_queue,
-+ sbi->s_delete_list.next == 0 && sbi->s_delete_inodes == 0);
-+}
-+
-+/* Instead of playing games with the inode flags, destruction, etc we just
-+ * create a new inode locally and put it on a list for the truncate thread.
-+ * We need large parts of the inode struct in order to complete the
-+ * truncate and unlink, so we may as well just have a real inode to do it.
-+ *
-+ * If we have any problem deferring the delete, just delete it right away.
-+ * If we defer it, we also mark how many blocks it would free, so that we
-+ * can keep the statfs data correct, and we know if we should sleep on the
-+ * delete thread when we run out of space.
-+ */
-+static void ext3_delete_inode_thread(struct inode *old_inode)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(old_inode->i_sb);
-+ struct ext3_inode_info *nei, *oei = EXT3_I(old_inode);
-+ struct inode *new_inode;
-+ unsigned long blocks = old_inode->i_blocks >> (old_inode->i_blkbits-9);
-+
-+ if (is_bad_inode(old_inode)) {
-+ clear_inode(old_inode);
-+ return;
-+ }
-+
-+ if (!test_opt(old_inode->i_sb, ASYNCDEL) || !sbi->s_delete_list.next)
-+ goto out_delete;
-+
-+ /* We may want to delete the inode immediately and not defer it */
-+ if (IS_SYNC(old_inode) || blocks <= EXT3_NDIR_BLOCKS)
-+ goto out_delete;
-+
-+ /* We can't use the delete thread as-is during real orphan recovery,
-+ * as we add to the orphan list here, causing ext3_orphan_cleanup()
-+ * to loop endlessly. It would be nice to do so, but needs work.
-+ */
-+ if (oei->i_state & EXT3_STATE_DELETE ||
-+ sbi->s_mount_state & EXT3_ORPHAN_FS) {
-+ ext3_debug("doing deferred inode %lu delete (%lu blocks)\n",
-+ old_inode->i_ino, blocks);
-+ goto out_delete;
-+ }
-+
-+ /* We can iget this inode again here, because our caller has unhashed
-+ * old_inode, so new_inode will be in a different inode struct.
-+ *
-+ * We need to ensure that the i_orphan pointers in the other inodes
-+ * point at the new inode copy instead of the old one so the orphan
-+ * list doesn't get corrupted when the old orphan inode is freed.
-+ */
-+ down(&sbi->s_orphan_lock);
-+
-+ sbi->s_mount_state |= EXT3_ORPHAN_FS;
-+ new_inode = iget(old_inode->i_sb, old_inode->i_ino);
-+ sbi->s_mount_state &= ~EXT3_ORPHAN_FS;
-+ if (is_bad_inode(new_inode)) {
-+ printk(KERN_WARNING "read bad inode %lu\n", old_inode->i_ino);
-+ iput(new_inode);
-+ new_inode = NULL;
-+ }
-+ if (!new_inode) {
-+ up(&sbi->s_orphan_lock);
-+ ext3_debug("delete inode %lu directly (bad read)\n",
-+ old_inode->i_ino);
-+ goto out_delete;
-+ }
-+ J_ASSERT(new_inode != old_inode);
-+
-+ J_ASSERT(!list_empty(&oei->i_orphan));
-+
-+ nei = EXT3_I(new_inode);
-+ /* Ugh. We need to insert new_inode into the same spot on the list
-+ * as old_inode was, to ensure the in-memory orphan list is still
-+ * in the same order as the on-disk orphan list (badness otherwise).
-+ */
-+ nei->i_orphan = oei->i_orphan;
-+ nei->i_orphan.next->prev = &nei->i_orphan;
-+ nei->i_orphan.prev->next = &nei->i_orphan;
-+ nei->i_state |= EXT3_STATE_DELETE;
-+ up(&sbi->s_orphan_lock);
-+
-+ clear_inode(old_inode);
-+
-+ spin_lock(&sbi->s_delete_lock);
-+ J_ASSERT(list_empty(&new_inode->i_dentry));
-+ list_add_tail(&new_inode->i_dentry, &sbi->s_delete_list);
-+ sbi->s_delete_blocks += blocks;
-+ sbi->s_delete_inodes++;
-+ spin_unlock(&sbi->s_delete_lock);
-+
-+ ext3_debug("delete inode %lu (%lu blocks) by thread\n",
-+ new_inode->i_ino, blocks);
-+
-+ wake_up(&sbi->s_delete_thread_queue);
-+ return;
-+
-+out_delete:
-+ ext3_delete_inode(old_inode);
-+}
-+#else
-+#define ext3_start_delete_thread(sbi) do {} while(0)
-+#define ext3_stop_delete_thread(sbi) do {} while(0)
-+#endif /* EXT3_DELETE_THREAD */
-+
- void ext3_put_super (struct super_block * sb)
- {
- struct ext3_sb_info *sbi = EXT3_SB(sb);
-@@ -407,6 +622,7 @@
- kdev_t j_dev = sbi->s_journal->j_dev;
- int i;
-
-+ J_ASSERT(sbi->s_delete_inodes == 0);
- ext3_xattr_put_super(sb);
- journal_destroy(sbi->s_journal);
- if (!(sb->s_flags & MS_RDONLY)) {
-@@ -455,7 +671,11 @@
- write_inode: ext3_write_inode, /* BKL not held. Don't need */
- dirty_inode: ext3_dirty_inode, /* BKL not held. We take it */
- put_inode: ext3_put_inode, /* BKL not held. Don't need */
-+#ifdef EXT3_DELETE_THREAD
-+ delete_inode: ext3_delete_inode_thread,/* BKL not held. We take it */
-+#else
- delete_inode: ext3_delete_inode, /* BKL not held. We take it */
-+#endif
- put_super: ext3_put_super, /* BKL held */
- write_super: ext3_write_super, /* BKL held */
- sync_fs: ext3_sync_fs,
-@@ -524,6 +744,13 @@
- clear_opt (*mount_options, XATTR_USER);
- else
- #endif
-+#ifdef EXT3_DELETE_THREAD
-+ if (!strcmp(this_char, "asyncdel"))
-+ set_opt(*mount_options, ASYNCDEL);
-+ else if (!strcmp(this_char, "noasyncdel"))
-+ clear_opt(*mount_options, ASYNCDEL);
-+ else
-+#endif
- if (!strcmp (this_char, "bsddf"))
- clear_opt (*mount_options, MINIX_DF);
- else if (!strcmp (this_char, "nouid32")) {
-@@ -1223,6 +1450,7 @@
- }
-
- ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY);
-+ ext3_start_delete_thread(sb);
- /*
- * akpm: core read_super() calls in here with the superblock locked.
- * That deadlocks, because orphan cleanup needs to lock the superblock
-@@ -1614,7 +1842,12 @@
- static int ext3_sync_fs(struct super_block *sb)
- {
- tid_t target;
--
-+
-+ if (atomic_read(&sb->s_active) == 0) {
-+ /* fs is being umounted: time to stop delete thread */
-+ ext3_stop_delete_thread(EXT3_SB(sb));
-+ }
-+
- sb->s_dirt = 0;
- target = log_start_commit(EXT3_SB(sb)->s_journal, NULL);
- log_wait_commit(EXT3_SB(sb)->s_journal, target);
-@@ -1678,6 +1911,9 @@
- if (!parse_options(data, &tmp, sbi, &tmp, 1))
- return -EINVAL;
-
-+ if (!test_opt(sb, ASYNCDEL) || (*flags & MS_RDONLY))
-+ ext3_stop_delete_thread(sbi);
-+
- if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
- ext3_abort(sb, __FUNCTION__, "Abort forced by user");
-
-Index: linux-2.4.21-suse/fs/ext3/inode.c
-===================================================================
---- linux-2.4.21-suse.orig/fs/ext3/inode.c 2004-01-13 17:38:09.000000000 +0300
-+++ linux-2.4.21-suse/fs/ext3/inode.c 2004-01-13 17:38:10.000000000 +0300
-@@ -2552,6 +2552,118 @@
- return err;
- }
-
-+#ifdef EXT3_DELETE_THREAD
-+/* Move blocks from to-be-truncated inode over to a new inode, and delete
-+ * that one from the delete thread instead. This avoids a lot of latency
-+ * when truncating large files.
-+ *
-+ * If we have any problem deferring the truncate, just truncate it right away.
-+ * If we defer it, we also mark how many blocks it would free, so that we
-+ * can keep the statfs data correct, and we know if we should sleep on the
-+ * delete thread when we run out of space.
-+ */
-+void ext3_truncate_thread(struct inode *old_inode)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(old_inode->i_sb);
-+ struct ext3_inode_info *nei, *oei = EXT3_I(old_inode);
-+ struct inode *new_inode;
-+ handle_t *handle;
-+ unsigned long blocks = old_inode->i_blocks >> (old_inode->i_blkbits-9);
-+
-+ if (!test_opt(old_inode->i_sb, ASYNCDEL) || !sbi->s_delete_list.next)
-+ goto out_truncate;
-+
-+ /* XXX This is a temporary limitation for code simplicity.
-+ * We could truncate to arbitrary sizes at some later time.
-+ */
-+ if (old_inode->i_size != 0)
-+ goto out_truncate;
-+
-+ /* We may want to truncate the inode immediately and not defer it */
-+ if (IS_SYNC(old_inode) || blocks <= EXT3_NDIR_BLOCKS ||
-+ old_inode->i_size > oei->i_disksize)
-+ goto out_truncate;
-+
-+ /* We can't use the delete thread as-is during real orphan recovery,
-+ * as we add to the orphan list here, causing ext3_orphan_cleanup()
-+ * to loop endlessly. It would be nice to do so, but needs work.
-+ */
-+ if (oei->i_state & EXT3_STATE_DELETE ||
-+ sbi->s_mount_state & EXT3_ORPHAN_FS) {
-+ ext3_debug("doing deferred inode %lu delete (%lu blocks)\n",
-+ old_inode->i_ino, blocks);
-+ goto out_truncate;
-+ }
-+
-+ ext3_discard_prealloc(old_inode);
-+
-+ /* old_inode = 1
-+ * new_inode = sb + GDT + ibitmap
-+ * orphan list = 1 inode/superblock for add, 2 inodes for del
-+ * quota files = 2 * EXT3_SINGLEDATA_TRANS_BLOCKS
-+ */
-+ handle = ext3_journal_start(old_inode, 7);
-+ if (IS_ERR(handle))
-+ goto out_truncate;
-+
-+ new_inode = ext3_new_inode(handle, old_inode, old_inode->i_mode);
-+ if (IS_ERR(new_inode)) {
-+ ext3_debug("truncate inode %lu directly (no new inodes)\n",
-+ old_inode->i_ino);
-+ goto out_journal;
-+ }
-+
-+ nei = EXT3_I(new_inode);
-+
-+ down_write(&oei->truncate_sem);
-+ new_inode->i_size = old_inode->i_size;
-+ new_inode->i_blocks = old_inode->i_blocks;
-+ new_inode->i_uid = old_inode->i_uid;
-+ new_inode->i_gid = old_inode->i_gid;
-+ new_inode->i_nlink = 0;
-+
-+ /* FIXME when we do arbitrary truncates */
-+ old_inode->i_blocks = oei->i_file_acl ? old_inode->i_blksize / 512 : 0;
-+ old_inode->i_mtime = old_inode->i_ctime = CURRENT_TIME;
-+
-+ memcpy(nei->i_data, oei->i_data, sizeof(nei->i_data));
-+ memset(oei->i_data, 0, sizeof(oei->i_data));
-+
-+ nei->i_disksize = oei->i_disksize;
-+ nei->i_state |= EXT3_STATE_DELETE;
-+ up_write(&oei->truncate_sem);
-+
-+ if (ext3_orphan_add(handle, new_inode) < 0)
-+ goto out_journal;
-+
-+ if (ext3_orphan_del(handle, old_inode) < 0) {
-+ ext3_orphan_del(handle, new_inode);
-+ iput(new_inode);
-+ goto out_journal;
-+ }
-+
-+ ext3_journal_stop(handle, old_inode);
-+
-+ spin_lock(&sbi->s_delete_lock);
-+ J_ASSERT(list_empty(&new_inode->i_dentry));
-+ list_add_tail(&new_inode->i_dentry, &sbi->s_delete_list);
-+ sbi->s_delete_blocks += blocks;
-+ sbi->s_delete_inodes++;
-+ spin_unlock(&sbi->s_delete_lock);
-+
-+ ext3_debug("delete inode %lu (%lu blocks) by thread\n",
-+ new_inode->i_ino, blocks);
-+
-+ wake_up(&sbi->s_delete_thread_queue);
-+ return;
-+
-+out_journal:
-+ ext3_journal_stop(handle, old_inode);
-+out_truncate:
-+ ext3_truncate(old_inode);
-+}
-+#endif /* EXT3_DELETE_THREAD */
-+
- /*
- * On success, We end up with an outstanding reference count against
- * iloc->bh. This _must_ be cleaned up later.
-Index: linux-2.4.21-suse/fs/ext3/file.c
-===================================================================
---- linux-2.4.21-suse.orig/fs/ext3/file.c 2004-01-12 19:49:25.000000000 +0300
-+++ linux-2.4.21-suse/fs/ext3/file.c 2004-01-13 17:38:10.000000000 +0300
-@@ -125,7 +125,11 @@
- };
-
- struct inode_operations ext3_file_inode_operations = {
-+#ifdef EXT3_DELETE_THREAD
-+ truncate: ext3_truncate_thread, /* BKL held */
-+#else
- truncate: ext3_truncate, /* BKL held */
-+#endif
- setattr: ext3_setattr, /* BKL held */
- setxattr: ext3_setxattr, /* BKL held */
- getxattr: ext3_getxattr, /* BKL held */
-Index: linux-2.4.21-suse/include/linux/ext3_fs.h
-===================================================================
---- linux-2.4.21-suse.orig/include/linux/ext3_fs.h 2004-01-13 17:38:09.000000000 +0300
-+++ linux-2.4.21-suse/include/linux/ext3_fs.h 2004-01-13 17:38:10.000000000 +0300
-@@ -193,6 +193,7 @@
- */
- #define EXT3_STATE_JDATA 0x00000001 /* journaled data exists */
- #define EXT3_STATE_NEW 0x00000002 /* inode is newly created */
-+#define EXT3_STATE_DELETE 0x00000010 /* deferred delete inode */
-
- /*
- * ioctl commands
-@@ -320,6 +321,7 @@
- #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */
- #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */
- #define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
-+#define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */
-
- /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
- #ifndef _LINUX_EXT2_FS_H
-@@ -697,6 +699,9 @@
- extern void ext3_dirty_inode(struct inode *);
- extern int ext3_change_inode_journal_flag(struct inode *, int);
- extern void ext3_truncate (struct inode *);
-+#ifdef EXT3_DELETE_THREAD
-+extern void ext3_truncate_thread(struct inode *inode);
-+#endif
- extern void ext3_set_inode_flags(struct inode *);
-
- /* ioctl.c */
-Index: linux-2.4.21-suse/include/linux/ext3_fs_sb.h
-===================================================================
---- linux-2.4.21-suse.orig/include/linux/ext3_fs_sb.h 2004-01-12 19:49:25.000000000 +0300
-+++ linux-2.4.21-suse/include/linux/ext3_fs_sb.h 2004-01-13 17:38:10.000000000 +0300
-@@ -29,6 +29,8 @@
-
- #define EXT3_MAX_GROUP_LOADED 8
-
-+#define EXT3_DELETE_THREAD
-+
- /*
- * third extended-fs super-block data in memory
- */
-@@ -76,6 +78,14 @@
- struct timer_list turn_ro_timer; /* For turning read-only (crash simulation) */
- wait_queue_head_t ro_wait_queue; /* For people waiting for the fs to go read-only */
- #endif
-+#ifdef EXT3_DELETE_THREAD
-+ spinlock_t s_delete_lock;
-+ struct list_head s_delete_list;
-+ unsigned long s_delete_blocks;
-+ unsigned long s_delete_inodes;
-+ wait_queue_head_t s_delete_thread_queue;
-+ wait_queue_head_t s_delete_waiter_queue;
-+#endif
- };
-
- #endif /* _LINUX_EXT3_FS_SB */
+++ /dev/null
-diff -rupN linux-2.4.24.orig/fs/ext3/namei.c linux-2.4.24/fs/ext3/namei.c
---- linux-2.4.24.orig/fs/ext3/namei.c Tue Oct 5 10:34:28 2004
-+++ linux-2.4.24/fs/ext3/namei.c Tue Oct 5 10:43:12 2004
-@@ -1112,6 +1112,7 @@ static struct dentry *ext3_lookup(struct
- dentry->d_flags |= DCACHE_CROSS_REF;
- dentry->d_generation = mds[1];
- dentry->d_mdsnum = mds[0];
-+ dentry->d_fid = mds[2];
- dentry->d_inum = ino;
- d_add(dentry, NULL);
- return NULL;
-@@ -1334,7 +1335,8 @@ static int add_dirent_to_buf(handle_t *h
- if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_MDSNUM)
- && (dentry->d_flags & DCACHE_CROSS_REF)
- && (dentry->d_mdsnum != EXT3_SB(sb)->s_mdsnum))
-- reclen += 8; /* we need space to store mds num */
-+ reclen += 12; /* we need space to store mds num,
-+ * inode num and fid num. */
- if (!de) {
- de = (struct ext3_dir_entry_2 *)bh->b_data;
- top = bh->b_data + dir->i_sb->s_blocksize - reclen;
-@@ -1387,6 +1389,7 @@ static int add_dirent_to_buf(handle_t *h
- mds = (__u32 *)((char *)de + EXT3_DIR_REC_LEN(namelen));
- mds[0] = cpu_to_le32(dentry->d_mdsnum);
- mds[1] = cpu_to_le32(dentry->d_generation);
-+ mds[2] = cpu_to_le32(dentry->d_fid);
- de->inode = cpu_to_le32(dentry->d_inum);
- de->file_type = 128;
- } else {
-diff -rupN linux-2.4.24.orig/include/linux/dcache.h linux-2.4.24/include/linux/dcache.h
---- linux-2.4.24.orig/include/linux/dcache.h Tue Oct 5 10:34:28 2004
-+++ linux-2.4.24/include/linux/dcache.h Tue Oct 5 10:43:45 2004
-@@ -123,6 +123,7 @@ struct dentry {
- unsigned d_inum; /* for cross-fs references (Lustre) */
- unsigned d_mdsnum; /* for cross-fs references (Lustre) */
- unsigned d_generation; /* for cross-fs references (Lustre) */
-+ unsigned d_fid; /* for cross-fs references (Lustre) */
- struct dentry * d_parent; /* parent directory */
- struct list_head d_hash; /* lookup hash list */
- struct list_head d_lru; /* d_count = 0 LRU list */
-diff -rupN linux-2.4.24.orig/include/linux/ext3_fs.h linux-2.4.24/include/linux/ext3_fs.h
---- linux-2.4.24.orig/include/linux/ext3_fs.h Tue Oct 5 10:34:28 2004
-+++ linux-2.4.24/include/linux/ext3_fs.h Tue Oct 5 10:44:29 2004
-@@ -589,7 +589,7 @@ struct ext3_dir_entry_2 {
- #define EXT3_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT3_DIR_ROUND) & \
- ~EXT3_DIR_ROUND)
- #define EXT3_DIR_REC_LEN_DE(de) (EXT3_DIR_REC_LEN((de)->name_len) + \
-- (((de)->file_type & 128) ? 8 : 0))
-+ (((de)->file_type & 128) ? 12 : 0))
-
- /*
- * Hash Tree Directory indexing
+++ /dev/null
- fs/ext3/ialloc.c | 6
- fs/ext3/inode.c | 12
- fs/ext3/super.c | 6
- fs/ext3/xattr.c | 597 +++++++++++++++++++++++++++++++++++++++++++++-
- include/linux/ext3_fs.h | 2
- include/linux/ext3_fs_i.h | 3
- 6 files changed, 615 insertions(+), 11 deletions(-)
-
---- linux-2.4.22-ac1/fs/ext3/ialloc.c~ext3-ea-in-inode-2.4.22-rh 2003-10-08 13:57:56.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext3/ialloc.c 2003-10-08 15:13:31.000000000 +0400
-@@ -715,6 +715,12 @@ have_bit_and_group:
- insert_inode_hash(inode);
- inode->i_generation = sb->u.ext3_sb.s_next_generation++;
-
-+ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) {
-+ inode->u.ext3_i.i_extra_isize = sizeof(__u16) /* i_extra_isize */
-+ + sizeof(__u16); /* i_pad1 */
-+ } else
-+ inode->u.ext3_i.i_extra_isize = 0;
-+
- inode->u.ext3_i.i_state = EXT3_STATE_NEW;
- err = ext3_get_inode_loc_new(inode, &iloc, 1);
- if (err) goto fail;
---- linux-2.4.22-ac1/fs/ext3/inode.c~ext3-ea-in-inode-2.4.22-rh 2003-10-08 13:57:57.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext3/inode.c 2003-10-08 15:14:57.000000000 +0400
-@@ -2229,6 +2229,12 @@ void ext3_read_inode(struct inode * inod
- inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block];
- INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
-
-+ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE)
-+ inode->u.ext3_i.i_extra_isize =
-+ le16_to_cpu(raw_inode->i_extra_isize);
-+ else
-+ inode->u.ext3_i.i_extra_isize = 0;
-+
- if (S_ISREG(inode->i_mode)) {
- inode->i_op = &ext3_file_inode_operations;
- inode->i_fop = &ext3_file_operations;
-@@ -2277,6 +2283,8 @@ static int ext3_do_update_inode(handle_t
- if (err)
- goto out_brelse;
- }
-+ if (EXT3_I(inode)->i_state & EXT3_STATE_NEW)
-+ memset(raw_inode, 0, EXT3_INODE_SIZE(inode->i_sb));
- raw_inode->i_mode = cpu_to_le16(inode->i_mode);
- if(!(test_opt(inode->i_sb, NO_UID32))) {
- raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid));
-@@ -2360,6 +2368,10 @@ static int ext3_do_update_inode(handle_t
- else for (block = 0; block < EXT3_N_BLOCKS; block++)
- raw_inode->i_block[block] = inode->u.ext3_i.i_data[block];
-
-+ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE)
-+ raw_inode->i_extra_isize =
-+ cpu_to_le16(EXT3_I(inode)->i_extra_isize);
-+
- BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
- rc = ext3_journal_dirty_metadata(handle, bh);
- if (!err)
---- linux-2.4.22-ac1/fs/ext3/super.c~ext3-ea-in-inode-2.4.22-rh 2003-10-08 13:57:57.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext3/super.c 2003-10-08 15:13:31.000000000 +0400
-@@ -1299,8 +1299,10 @@ struct super_block * ext3_read_super (st
- } else {
- sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
- sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
-- if (sbi->s_inode_size != EXT3_GOOD_OLD_INODE_SIZE) {
-- printk (KERN_ERR
-+ if ((sbi->s_inode_size < EXT3_GOOD_OLD_INODE_SIZE) ||
-+ (sbi->s_inode_size & (sbi->s_inode_size - 1)) ||
-+ (sbi->s_inode_size > blocksize)) {
-+ printk (KERN_ERR
- "EXT3-fs: unsupported inode size: %d\n",
- sbi->s_inode_size);
- goto failed_mount;
---- linux-2.4.22-ac1/fs/ext3/xattr.c~ext3-ea-in-inode-2.4.22-rh 2003-10-08 13:57:56.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext3/xattr.c 2003-10-12 16:36:07.000000000 +0400
-@@ -100,6 +100,9 @@
- static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *,
- struct ext3_xattr_header *);
-
-+int ext3_xattr_block_set(handle_t *, struct inode *, int, const char *,
-+ const void *, size_t, int);
-+
- #ifdef CONFIG_EXT3_FS_XATTR_SHARING
-
- static int ext3_xattr_cache_insert(struct buffer_head *);
-@@ -348,17 +351,12 @@ ext3_removexattr(struct dentry *dentry,
- }
-
- /*
-- * ext3_xattr_get()
-- *
-- * Copy an extended attribute into the buffer
-- * provided, or compute the buffer size required.
-- * Buffer is NULL to compute the size of the buffer required.
-+ * ext3_xattr_block_get()
- *
-- * Returns a negative error number on failure, or the number of bytes
-- * used / required on success.
-+ * routine looks for attribute in EA block and returns it's value and size
- */
- int
--ext3_xattr_get(struct inode *inode, int name_index, const char *name,
-+ext3_xattr_block_get(struct inode *inode, int name_index, const char *name,
- void *buffer, size_t buffer_size)
- {
- struct buffer_head *bh = NULL;
-@@ -447,6 +445,94 @@ cleanup:
- }
-
- /*
-+ * ext3_xattr_ibode_get()
-+ *
-+ * routine looks for attribute in inode body and returns it's value and size
-+ */
-+int
-+ext3_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
-+ void *buffer, size_t buffer_size)
-+{
-+ int size, name_len = strlen(name), storage_size;
-+ struct ext3_xattr_entry *last;
-+ struct ext3_inode *raw_inode;
-+ struct ext3_iloc iloc;
-+ char *start, *end;
-+ int ret = -ENOENT;
-+
-+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
-+ return -ENOENT;
-+
-+ ret = ext3_get_inode_loc(inode, &iloc);
-+ if (ret)
-+ return ret;
-+ raw_inode = iloc.raw_inode;
-+
-+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
-+ EXT3_GOOD_OLD_INODE_SIZE -
-+ EXT3_I(inode)->i_extra_isize -
-+ sizeof(__u32);
-+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
-+ EXT3_I(inode)->i_extra_isize;
-+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) {
-+ brelse(iloc.bh);
-+ return -ENOENT;
-+ }
-+ start += sizeof(__u32);
-+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
-+
-+ last = (struct ext3_xattr_entry *) start;
-+ while (!IS_LAST_ENTRY(last)) {
-+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
-+ if (le32_to_cpu(last->e_value_size) > storage_size ||
-+ (char *) next >= end) {
-+ ext3_error(inode->i_sb, "ext3_xattr_ibody_get",
-+ "inode %ld", inode->i_ino);
-+ brelse(iloc.bh);
-+ return -EIO;
-+ }
-+ if (name_index == last->e_name_index &&
-+ name_len == last->e_name_len &&
-+ !memcmp(name, last->e_name, name_len))
-+ goto found;
-+ last = next;
-+ }
-+
-+ /* can't find EA */
-+ brelse(iloc.bh);
-+ return -ENOENT;
-+
-+found:
-+ size = le32_to_cpu(last->e_value_size);
-+ if (buffer) {
-+ ret = -ERANGE;
-+ if (buffer_size >= size) {
-+ memcpy(buffer, start + le16_to_cpu(last->e_value_offs),
-+ size);
-+ ret = size;
-+ }
-+ } else
-+ ret = size;
-+ brelse(iloc.bh);
-+ return ret;
-+}
-+
-+int ext3_xattr_get(struct inode *inode, int name_index, const char *name,
-+ void *buffer, size_t buffer_size)
-+{
-+ int err;
-+
-+ /* try to find attribute in inode body */
-+ err = ext3_xattr_ibody_get(inode, name_index, name,
-+ buffer, buffer_size);
-+ if (err < 0)
-+ /* search was unsuccessful, try to find EA in dedicated block */
-+ err = ext3_xattr_block_get(inode, name_index, name,
-+ buffer, buffer_size);
-+ return err;
-+}
-+
-+/*
- * ext3_xattr_list()
- *
- * Copy a list of attribute names into the buffer
-@@ -457,7 +543,7 @@ cleanup:
- * used / required on success.
- */
- int
--ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
-+ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
- {
- struct buffer_head *bh = NULL;
- struct ext3_xattr_entry *entry;
-@@ -530,6 +616,131 @@ cleanup:
- return error;
- }
-
-+/* ext3_xattr_ibody_list()
-+ *
-+ * generate list of attributes stored in inode body
-+ */
-+int
-+ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size)
-+{
-+ struct ext3_xattr_entry *last;
-+ struct ext3_inode *raw_inode;
-+ char *start, *end, *buf;
-+ struct ext3_iloc iloc;
-+ int storage_size;
-+ int ret;
-+ int size = 0;
-+
-+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
-+ return 0;
-+
-+ ret = ext3_get_inode_loc(inode, &iloc);
-+ if (ret)
-+ return ret;
-+ raw_inode = iloc.raw_inode;
-+
-+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
-+ EXT3_GOOD_OLD_INODE_SIZE -
-+ EXT3_I(inode)->i_extra_isize -
-+ sizeof(__u32);
-+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
-+ EXT3_I(inode)->i_extra_isize;
-+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) {
-+ brelse(iloc.bh);
-+ return 0;
-+ }
-+ start += sizeof(__u32);
-+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
-+
-+ last = (struct ext3_xattr_entry *) start;
-+ while (!IS_LAST_ENTRY(last)) {
-+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
-+ struct ext3_xattr_handler *handler;
-+ if (le32_to_cpu(last->e_value_size) > storage_size ||
-+ (char *) next >= end) {
-+ ext3_error(inode->i_sb, "ext3_xattr_ibody_list",
-+ "inode %ld", inode->i_ino);
-+ brelse(iloc.bh);
-+ return -EIO;
-+ }
-+ handler = ext3_xattr_handler(last->e_name_index);
-+ if (handler)
-+ size += handler->list(NULL, inode, last->e_name,
-+ last->e_name_len);
-+ last = next;
-+ }
-+
-+ if (!buffer) {
-+ ret = size;
-+ goto cleanup;
-+ } else {
-+ ret = -ERANGE;
-+ if (size > buffer_size)
-+ goto cleanup;
-+ }
-+
-+ last = (struct ext3_xattr_entry *) start;
-+ buf = buffer;
-+ while (!IS_LAST_ENTRY(last)) {
-+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
-+ struct ext3_xattr_handler *handler;
-+ handler = ext3_xattr_handler(last->e_name_index);
-+ if (handler)
-+ buf += handler->list(buf, inode, last->e_name,
-+ last->e_name_len);
-+ last = next;
-+ }
-+ ret = size;
-+cleanup:
-+ brelse(iloc.bh);
-+ return ret;
-+}
-+
-+/*
-+ * ext3_xattr_list()
-+ *
-+ * Copy a list of attribute names into the buffer
-+ * provided, or compute the buffer size required.
-+ * Buffer is NULL to compute the size of the buffer required.
-+ *
-+ * Returns a negative error number on failure, or the number of bytes
-+ * used / required on success.
-+ */
-+int
-+ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
-+{
-+ int error;
-+ int size = buffer_size;
-+
-+ /* get list of attributes stored in inode body */
-+ error = ext3_xattr_ibody_list(inode, buffer, buffer_size);
-+ if (error < 0) {
-+ /* some error occured while collecting
-+ * attributes in inode body */
-+ size = 0;
-+ goto cleanup;
-+ }
-+ size = error;
-+
-+ /* get list of attributes stored in dedicated block */
-+ if (buffer) {
-+ buffer_size -= error;
-+ if (buffer_size <= 0) {
-+ buffer = NULL;
-+ buffer_size = 0;
-+ } else
-+ buffer += error;
-+ }
-+
-+ error = ext3_xattr_block_list(inode, buffer, buffer_size);
-+ if (error < 0)
-+ /* listing was successful, so we return len */
-+ size = 0;
-+
-+cleanup:
-+ return error + size;
-+}
-+
- /*
- * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
- * not set, set it.
-@@ -553,6 +764,279 @@ static void ext3_xattr_update_super_bloc
- }
-
- /*
-+ * ext3_xattr_ibody_find()
-+ *
-+ * search attribute and calculate free space in inode body
-+ * NOTE: free space includes space our attribute hold
-+ */
-+int
-+ext3_xattr_ibody_find(struct inode *inode, int name_index,
-+ const char *name, struct ext3_xattr_entry *rentry, int *free)
-+{
-+ struct ext3_xattr_entry *last;
-+ struct ext3_inode *raw_inode;
-+ int name_len = strlen(name);
-+ int err, storage_size;
-+ struct ext3_iloc iloc;
-+ char *start, *end;
-+ int ret = -ENOENT;
-+
-+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
-+ return ret;
-+
-+ err = ext3_get_inode_loc(inode, &iloc);
-+ if (err)
-+ return -EIO;
-+ raw_inode = iloc.raw_inode;
-+
-+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
-+ EXT3_GOOD_OLD_INODE_SIZE -
-+ EXT3_I(inode)->i_extra_isize -
-+ sizeof(__u32);
-+ *free = storage_size - sizeof(__u32);
-+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
-+ EXT3_I(inode)->i_extra_isize;
-+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) {
-+ brelse(iloc.bh);
-+ return -ENOENT;
-+ }
-+ start += sizeof(__u32);
-+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
-+
-+ last = (struct ext3_xattr_entry *) start;
-+ while (!IS_LAST_ENTRY(last)) {
-+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
-+ if (le32_to_cpu(last->e_value_size) > storage_size ||
-+ (char *) next >= end) {
-+ ext3_error(inode->i_sb, "ext3_xattr_ibody_find",
-+ "inode %ld", inode->i_ino);
-+ brelse(iloc.bh);
-+ return -EIO;
-+ }
-+
-+ if (name_index == last->e_name_index &&
-+ name_len == last->e_name_len &&
-+ !memcmp(name, last->e_name, name_len)) {
-+ memcpy(rentry, last, sizeof(struct ext3_xattr_entry));
-+ ret = 0;
-+ } else {
-+ *free -= EXT3_XATTR_LEN(last->e_name_len);
-+ *free -= le32_to_cpu(last->e_value_size);
-+ }
-+ last = next;
-+ }
-+
-+ brelse(iloc.bh);
-+ return ret;
-+}
-+
-+/*
-+ * ext3_xattr_block_find()
-+ *
-+ * search attribute and calculate free space in EA block (if it allocated)
-+ * NOTE: free space includes space our attribute hold
-+ */
-+int
-+ext3_xattr_block_find(struct inode *inode, int name_index, const char *name,
-+ struct ext3_xattr_entry *rentry, int *free)
-+{
-+ struct buffer_head *bh = NULL;
-+ struct ext3_xattr_entry *entry;
-+ char *end;
-+ int name_len, error = -ENOENT;
-+
-+ if (!EXT3_I(inode)->i_file_acl) {
-+ *free = inode->i_sb->s_blocksize -
-+ sizeof(struct ext3_xattr_header) -
-+ sizeof(__u32);
-+ return -ENOENT;
-+ }
-+ ea_idebug(inode, "reading block %d", EXT3_I(inode)->i_file_acl);
-+ bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl);
-+ if (!bh)
-+ return -EIO;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
-+ end = bh->b_data + bh->b_size;
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext3_error(inode->i_sb, "ext3_xattr_get",
-+ "inode %ld: bad block %d", inode->i_ino,
-+ EXT3_I(inode)->i_file_acl);
-+ brelse(bh);
-+ return -EIO;
-+ }
-+ /* find named attribute */
-+ name_len = strlen(name);
-+ *free = bh->b_size - sizeof(__u32);
-+
-+ entry = FIRST_ENTRY(bh);
-+ while (!IS_LAST_ENTRY(entry)) {
-+ struct ext3_xattr_entry *next =
-+ EXT3_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (name_index == entry->e_name_index &&
-+ name_len == entry->e_name_len &&
-+ memcmp(name, entry->e_name, name_len) == 0) {
-+ memcpy(rentry, entry, sizeof(struct ext3_xattr_entry));
-+ error = 0;
-+ } else {
-+ *free -= EXT3_XATTR_LEN(entry->e_name_len);
-+ *free -= le32_to_cpu(entry->e_value_size);
-+ }
-+ entry = next;
-+ }
-+ brelse(bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * ext3_xattr_inode_set()
-+ *
-+ * this routine add/remove/replace attribute in inode body
-+ */
-+int
-+ext3_xattr_ibody_set(handle_t *handle, struct inode *inode, int name_index,
-+ const char *name, const void *value, size_t value_len,
-+ int flags)
-+{
-+ struct ext3_xattr_entry *last, *next, *here = NULL;
-+ struct ext3_inode *raw_inode;
-+ int name_len = strlen(name);
-+ int esize = EXT3_XATTR_LEN(name_len);
-+ struct buffer_head *bh;
-+ int err, storage_size;
-+ struct ext3_iloc iloc;
-+ int free, min_offs;
-+ char *start, *end;
-+
-+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE)
-+ return -ENOSPC;
-+
-+ err = ext3_get_inode_loc(inode, &iloc);
-+ if (err)
-+ return err;
-+ raw_inode = iloc.raw_inode;
-+ bh = iloc.bh;
-+
-+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size -
-+ EXT3_GOOD_OLD_INODE_SIZE -
-+ EXT3_I(inode)->i_extra_isize -
-+ sizeof(__u32);
-+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE +
-+ EXT3_I(inode)->i_extra_isize;
-+ if ((*(__u32*) start) != EXT3_XATTR_MAGIC) {
-+ /* inode had no attributes before */
-+ *((__u32*) start) = cpu_to_le32(EXT3_XATTR_MAGIC);
-+ }
-+ start += sizeof(__u32);
-+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
-+ min_offs = storage_size;
-+ free = storage_size - sizeof(__u32);
-+
-+ last = (struct ext3_xattr_entry *) start;
-+ while (!IS_LAST_ENTRY(last)) {
-+ next = EXT3_XATTR_NEXT(last);
-+ if (le32_to_cpu(last->e_value_size) > storage_size ||
-+ (char *) next >= end) {
-+ ext3_error(inode->i_sb, "ext3_xattr_ibody_set",
-+ "inode %ld", inode->i_ino);
-+ brelse(bh);
-+ return -EIO;
-+ }
-+
-+ if (last->e_value_size) {
-+ int offs = le16_to_cpu(last->e_value_offs);
-+ if (offs < min_offs)
-+ min_offs = offs;
-+ }
-+ if (name_index == last->e_name_index &&
-+ name_len == last->e_name_len &&
-+ !memcmp(name, last->e_name, name_len))
-+ here = last;
-+ else {
-+ /* we calculate all but our attribute
-+ * because it will be removed before changing */
-+ free -= EXT3_XATTR_LEN(last->e_name_len);
-+ free -= le32_to_cpu(last->e_value_size);
-+ }
-+ last = next;
-+ }
-+
-+ if (value && (esize + value_len > free)) {
-+ brelse(bh);
-+ return -ENOSPC;
-+ }
-+
-+ err = ext3_reserve_inode_write(handle, inode, &iloc);
-+ if (err) {
-+ brelse(bh);
-+ return err;
-+ }
-+
-+ if (here) {
-+ /* time to remove old value */
-+ struct ext3_xattr_entry *e;
-+ int size = le32_to_cpu(here->e_value_size);
-+ int border = le16_to_cpu(here->e_value_offs);
-+ char *src;
-+
-+ /* move tail */
-+ memmove(start + min_offs + size, start + min_offs,
-+ border - min_offs);
-+
-+ /* recalculate offsets */
-+ e = (struct ext3_xattr_entry *) start;
-+ while (!IS_LAST_ENTRY(e)) {
-+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(e);
-+ int offs = le16_to_cpu(e->e_value_offs);
-+ if (offs < border)
-+ e->e_value_offs =
-+ cpu_to_le16(offs + size);
-+ e = next;
-+ }
-+ min_offs += size;
-+
-+ /* remove entry */
-+ border = EXT3_XATTR_LEN(here->e_name_len);
-+ src = (char *) here + EXT3_XATTR_LEN(here->e_name_len);
-+ size = (char *) last - src;
-+ if ((char *) here + size > end)
-+ printk("ALERT at %s:%d: 0x%p + %d > 0x%p\n",
-+ __FILE__, __LINE__, here, size, end);
-+ memmove(here, src, size);
-+ last = (struct ext3_xattr_entry *) ((char *) last - border);
-+ *((__u32 *) last) = 0;
-+ }
-+
-+ if (value) {
-+ int offs = min_offs - value_len;
-+ /* use last to create new entry */
-+ last->e_name_len = strlen(name);
-+ last->e_name_index = name_index;
-+ last->e_value_offs = cpu_to_le16(offs);
-+ last->e_value_size = cpu_to_le32(value_len);
-+ last->e_hash = last->e_value_block = 0;
-+ memset(last->e_name, 0, esize);
-+ memcpy(last->e_name, name, last->e_name_len);
-+ if (start + offs + value_len > end)
-+ printk("ALERT at %s:%d: 0x%p + %d + %d > 0x%p\n",
-+ __FILE__, __LINE__, start, offs,
-+ value_len, end);
-+ memcpy(start + offs, value, value_len);
-+ last = EXT3_XATTR_NEXT(last);
-+ *((__u32 *) last) = 0;
-+ }
-+
-+ ext3_mark_iloc_dirty(handle, inode, &iloc);
-+ brelse(bh);
-+
-+ return 0;
-+}
-+
-+/*
- * ext3_xattr_set()
- *
- * Create, replace or remove an extended attribute for this inode. Buffer
-@@ -566,6 +1050,101 @@ static void ext3_xattr_update_super_bloc
- */
- int
- ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
-+ const char *name, const void *value, size_t value_len, int flags)
-+{
-+ struct ext3_xattr_entry entry;
-+ int err, where = 0, found = 0, total;
-+ int free1 = -1, free2 = -1;
-+ int name_len;
-+
-+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
-+ name_index, name, value, (long)value_len);
-+
-+ if (IS_RDONLY(inode))
-+ return -EROFS;
-+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-+ return -EPERM;
-+ if (value == NULL)
-+ value_len = 0;
-+ if (name == NULL)
-+ return -EINVAL;
-+ name_len = strlen(name);
-+ if (name_len > 255 || value_len > inode->i_sb->s_blocksize)
-+ return -ERANGE;
-+
-+ /* try to find attribute in inode body */
-+ err = ext3_xattr_ibody_find(inode, name_index, name, &entry, &free1);
-+ if (err == 0) {
-+ /* found EA in inode */
-+ found = 1;
-+ where = 0;
-+ } else if (err == -ENOENT) {
-+ /* there is no such attribute in inode body */
-+ /* try to find attribute in dedicated block */
-+ err = ext3_xattr_block_find(inode, name_index, name,
-+ &entry, &free2);
-+ if (err != 0 && err != -ENOENT) {
-+ /* not found EA in block */
-+ goto finish;
-+ } else if (err == 0) {
-+ /* found EA in block */
-+ where = 1;
-+ found = 1;
-+ }
-+ } else
-+ goto finish;
-+
-+ /* check flags: may replace? may create ? */
-+ if (found && (flags & XATTR_CREATE)) {
-+ err = -EEXIST;
-+ goto finish;
-+ } else if (!found && (flags & XATTR_REPLACE)) {
-+ err = -ENODATA;
-+ goto finish;
-+ }
-+
-+ /* check if we have enough space to store attribute */
-+ total = EXT3_XATTR_LEN(strlen(name)) + value_len;
-+ if (free1 >= 0 && total > free1 && free2 >= 0 && total > free2) {
-+ /* have no enough space */
-+ err = -ENOSPC;
-+ goto finish;
-+ }
-+
-+ /* time to remove attribute */
-+ if (found) {
-+ if (where == 0) {
-+ /* EA is stored in inode body */
-+ ext3_xattr_ibody_set(handle, inode, name_index, name,
-+ NULL, 0, flags);
-+ } else {
-+ /* EA is stored in separated block */
-+ ext3_xattr_block_set(handle, inode, name_index, name,
-+ NULL, 0, flags);
-+ }
-+ }
-+
-+ /* try to store EA in inode body */
-+ err = ext3_xattr_ibody_set(handle, inode, name_index, name,
-+ value, value_len, flags);
-+ if (err) {
-+ /* can't store EA in inode body */
-+ /* try to store in block */
-+ err = ext3_xattr_block_set(handle, inode, name_index,
-+ name, value, value_len, flags);
-+ }
-+
-+finish:
-+ return err;
-+}
-+
-+/*
-+ * ext3_xattr_block_set()
-+ *
-+ * this routine add/remove/replace attribute in EA block
-+ */
-+int
-+ext3_xattr_block_set(handle_t *handle, struct inode *inode, int name_index,
- const char *name, const void *value, size_t value_len, int flags)
- {
- struct super_block *sb = inode->i_sb;
-@@ -603,6 +1181,7 @@ ext3_xattr_set(handle_t *handle, struct
- name_len = strlen(name);
- if (name_len > 255 || value_len > sb->s_blocksize)
- return -ERANGE;
-+
- down(&ext3_xattr_sem);
-
- if (block) {
---- linux-2.4.22-ac1/include/linux/ext3_fs.h~ext3-ea-in-inode-2.4.22-rh 2003-10-08 13:57:57.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/include/linux/ext3_fs.h 2003-10-08 15:13:31.000000000 +0400
-@@ -265,6 +265,8 @@ struct ext3_inode {
- __u32 m_i_reserved2[2];
- } masix2;
- } osd2; /* OS dependent 2 */
-+ __u16 i_extra_isize;
-+ __u16 i_pad1;
- };
-
- #define i_size_high i_dir_acl
---- linux-2.4.22-ac1/include/linux/ext3_fs_i.h~ext3-ea-in-inode-2.4.22-rh 2003-09-26 00:54:44.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/include/linux/ext3_fs_i.h 2003-10-08 15:13:31.000000000 +0400
-@@ -62,6 +62,9 @@ struct ext3_inode_info {
- */
- loff_t i_disksize;
-
-+ /* on-disk additional length */
-+ __u16 i_extra_isize;
-+
- /*
- * truncate_sem is for serialising ext3_truncate() against
- * ext3_getblock(). In the 2.4 ext2 design, great chunks of inode's
-
-_
+++ /dev/null
- fs/ext3/ext3-exports.c | 5 +++++
- 1 files changed, 5 insertions(+)
-
---- linux/fs/ext3/ext3-exports.c~ext3-error-export Mon Jul 14 19:30:50 2003
-+++ linux-mmonroe/fs/ext3/ext3-exports.c Mon Jul 14 19:32:37 2003
-@@ -21,3 +21,8 @@ EXPORT_SYMBOL(ext3_xattr_list);
- EXPORT_SYMBOL(ext3_xattr_set);
- EXPORT_SYMBOL(ext3_prep_san_write);
- EXPORT_SYMBOL(ext3_map_inode_page);
-+
-+EXPORT_SYMBOL(ext3_abort);
-+EXPORT_SYMBOL(ext3_decode_error);
-+EXPORT_SYMBOL(__ext3_std_error);
-+
-
-_
+++ /dev/null
-Index: linux-2.4.24-b1_4/fs/ext3/extents.c
-===================================================================
---- linux-2.4.24-b1_4.orig/fs/ext3/extents.c 2003-01-30 18:24:37.000000000 +0800
-+++ linux-2.4.24-b1_4/fs/ext3/extents.c 2004-09-30 14:04:33.000000000 +0800
-@@ -0,0 +1,2262 @@
-+/*
-+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
-+ * Written by Alex Tomas <alex@clusterfs.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public Licens
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-
-+ */
-+
-+/*
-+ * Extents support for EXT3
-+ *
-+ * TODO:
-+ * - ext3_ext_walk_space() sould not use ext3_ext_find_extent()
-+ * - ext3_ext_calc_credits() could take 'mergable' into account
-+ * - ext3*_error() should be used in some situations
-+ * - find_goal() [to be tested and improved]
-+ * - smart tree reduction
-+ * - arch-independence
-+ * common on-disk format for big/little-endian arch
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/fs.h>
-+#include <linux/time.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/jbd.h>
-+#include <linux/locks.h>
-+#include <linux/smp_lock.h>
-+#include <linux/highuid.h>
-+#include <linux/pagemap.h>
-+#include <linux/quotaops.h>
-+#include <linux/string.h>
-+#include <linux/slab.h>
-+#include <linux/ext3_extents.h>
-+#include <asm/uaccess.h>
-+
-+static handle_t *ext3_ext_journal_restart(handle_t *handle, int needed)
-+{
-+ int err;
-+
-+ if (handle->h_buffer_credits > needed)
-+ return handle;
-+ if (!ext3_journal_extend(handle, needed))
-+ return handle;
-+ err = ext3_journal_restart(handle, needed);
-+
-+ return handle;
-+}
-+
-+static int inline
-+ext3_ext_get_access_for_root(handle_t *h, struct ext3_extents_tree *tree)
-+{
-+ if (tree->ops->get_write_access)
-+ return tree->ops->get_write_access(h,tree->buffer);
-+ else
-+ return 0;
-+}
-+
-+static int inline
-+ext3_ext_mark_root_dirty(handle_t *h, struct ext3_extents_tree *tree)
-+{
-+ if (tree->ops->mark_buffer_dirty)
-+ return tree->ops->mark_buffer_dirty(h,tree->buffer);
-+ else
-+ return 0;
-+}
-+
-+/*
-+ * could return:
-+ * - EROFS
-+ * - ENOMEM
-+ */
-+static int ext3_ext_get_access(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
-+{
-+ int err;
-+
-+ if (path->p_bh) {
-+ /* path points to block */
-+ err = ext3_journal_get_write_access(handle, path->p_bh);
-+ } else {
-+ /* path points to leaf/index in inode body */
-+ err = ext3_ext_get_access_for_root(handle, tree);
-+ }
-+ return err;
-+}
-+
-+/*
-+ * could return:
-+ * - EROFS
-+ * - ENOMEM
-+ * - EIO
-+ */
-+static int ext3_ext_dirty(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
-+{
-+ int err;
-+ if (path->p_bh) {
-+ /* path points to block */
-+ err =ext3_journal_dirty_metadata(handle, path->p_bh);
-+ } else {
-+ /* path points to leaf/index in inode body */
-+ err = ext3_ext_mark_root_dirty(handle, tree);
-+ }
-+ return err;
-+}
-+
-+static int inline
-+ext3_ext_new_block(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, struct ext3_extent *ex,
-+ int *err)
-+{
-+ int goal, depth, newblock;
-+ struct inode *inode;
-+
-+ EXT_ASSERT(tree);
-+ if (tree->ops->new_block)
-+ return tree->ops->new_block(handle, tree, path, ex, err);
-+
-+ inode = tree->inode;
-+ depth = EXT_DEPTH(tree);
-+ if (path && depth > 0) {
-+ goal = path[depth-1].p_block;
-+ } else {
-+ struct ext3_inode_info *ei = EXT3_I(inode);
-+ unsigned long bg_start;
-+ unsigned long colour;
-+
-+ bg_start = (ei->i_block_group *
-+ EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
-+ le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
-+ colour = (current->pid % 16) *
-+ (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16);
-+ goal = bg_start + colour;
-+ }
-+
-+ newblock = ext3_new_block(handle, inode, goal, 0, 0, err);
-+ return newblock;
-+}
-+
-+static inline void ext3_ext_tree_changed(struct ext3_extents_tree *tree)
-+{
-+ struct ext3_extent_header *neh;
-+ neh = EXT_ROOT_HDR(tree);
-+ neh->eh_generation++;
-+}
-+
-+static inline int ext3_ext_space_block(struct ext3_extents_tree *tree)
-+{
-+ int size;
-+
-+ size = (tree->inode->i_sb->s_blocksize -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent);
-+#ifdef AGRESSIVE_TEST
-+ size = 6;
-+#endif
-+ return size;
-+}
-+
-+static inline int ext3_ext_space_block_idx(struct ext3_extents_tree *tree)
-+{
-+ int size;
-+
-+ size = (tree->inode->i_sb->s_blocksize -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent_idx);
-+#ifdef AGRESSIVE_TEST
-+ size = 5;
-+#endif
-+ return size;
-+}
-+
-+static inline int ext3_ext_space_root(struct ext3_extents_tree *tree)
-+{
-+ int size;
-+
-+ size = (tree->buffer_len - sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent);
-+#ifdef AGRESSIVE_TEST
-+ size = 3;
-+#endif
-+ return size;
-+}
-+
-+static inline int ext3_ext_space_root_idx(struct ext3_extents_tree *tree)
-+{
-+ int size;
-+
-+ size = (tree->buffer_len -
-+ sizeof(struct ext3_extent_header))
-+ / sizeof(struct ext3_extent_idx);
-+#ifdef AGRESSIVE_TEST
-+ size = 4;
-+#endif
-+ return size;
-+}
-+
-+static void ext3_ext_show_path(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
-+{
-+#ifdef EXT_DEBUG
-+ int k, l = path->p_depth;
-+
-+ ext_debug(tree, "path:");
-+ for (k = 0; k <= l; k++, path++) {
-+ if (path->p_idx) {
-+ ext_debug(tree, " %d->%d", path->p_idx->ei_block,
-+ path->p_idx->ei_leaf);
-+ } else if (path->p_ext) {
-+ ext_debug(tree, " %d:%d:%d",
-+ path->p_ext->ee_block,
-+ path->p_ext->ee_len,
-+ path->p_ext->ee_start);
-+ } else
-+ ext_debug(tree, " []");
-+ }
-+ ext_debug(tree, "\n");
-+#endif
-+}
-+
-+static void ext3_ext_show_leaf(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
-+{
-+#ifdef EXT_DEBUG
-+ int depth = EXT_DEPTH(tree);
-+ struct ext3_extent_header *eh;
-+ struct ext3_extent *ex;
-+ int i;
-+
-+ if (!path)
-+ return;
-+
-+ eh = path[depth].p_hdr;
-+ ex = EXT_FIRST_EXTENT(eh);
-+
-+ for (i = 0; i < eh->eh_entries; i++, ex++) {
-+ ext_debug(tree, "%d:%d:%d ",
-+ ex->ee_block, ex->ee_len, ex->ee_start);
-+ }
-+ ext_debug(tree, "\n");
-+#endif
-+}
-+
-+static void ext3_ext_drop_refs(struct ext3_ext_path *path)
-+{
-+ int depth = path->p_depth;
-+ int i;
-+
-+ for (i = 0; i <= depth; i++, path++)
-+ if (path->p_bh) {
-+ brelse(path->p_bh);
-+ path->p_bh = NULL;
-+ }
-+}
-+
-+/*
-+ * binary search for closest index by given block
-+ */
-+static inline void
-+ext3_ext_binsearch_idx(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, int block)
-+{
-+ struct ext3_extent_header *eh = path->p_hdr;
-+ struct ext3_extent_idx *ix;
-+ int l = 0, k, r;
-+
-+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
-+ EXT_ASSERT(eh->eh_entries <= eh->eh_max);
-+ EXT_ASSERT(eh->eh_entries > 0);
-+
-+ ext_debug(tree, "binsearch for %d(idx): ", block);
-+
-+ path->p_idx = ix = EXT_FIRST_INDEX(eh);
-+
-+ r = k = eh->eh_entries;
-+ while (k > 1) {
-+ k = (r - l) / 2;
-+ if (block < ix[l + k].ei_block)
-+ r -= k;
-+ else
-+ l += k;
-+ ext_debug(tree, "%d:%d:%d ", k, l, r);
-+ }
-+
-+ ix += l;
-+ path->p_idx = ix;
-+ ext_debug(tree, " -> %d->%d ", path->p_idx->ei_block, path->p_idx->ei_leaf);
-+
-+ while (l++ < r) {
-+ if (block < ix->ei_block)
-+ break;
-+ path->p_idx = ix++;
-+ }
-+ ext_debug(tree, " -> %d->%d\n", path->p_idx->ei_block,
-+ path->p_idx->ei_leaf);
-+
-+#ifdef CHECK_BINSEARCH
-+ {
-+ struct ext3_extent_idx *chix;
-+
-+ chix = ix = EXT_FIRST_INDEX(eh);
-+ for (k = 0; k < eh->eh_entries; k++, ix++) {
-+ if (k != 0 && ix->ei_block <= ix[-1].ei_block) {
-+ printk("k=%d, ix=0x%p, first=0x%p\n", k,
-+ ix, EXT_FIRST_INDEX(eh));
-+ printk("%u <= %u\n",
-+ ix->ei_block,ix[-1].ei_block);
-+ }
-+ EXT_ASSERT(k == 0 || ix->ei_block > ix[-1].ei_block);
-+ if (block < ix->ei_block)
-+ break;
-+ chix = ix;
-+ }
-+ EXT_ASSERT(chix == path->p_idx);
-+ }
-+#endif
-+
-+}
-+
-+/*
-+ * binary search for closest extent by given block
-+ */
-+static inline void
-+ext3_ext_binsearch(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, int block)
-+{
-+ struct ext3_extent_header *eh = path->p_hdr;
-+ struct ext3_extent *ex;
-+ int l = 0, k, r;
-+
-+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
-+ EXT_ASSERT(eh->eh_entries <= eh->eh_max);
-+
-+ if (eh->eh_entries == 0) {
-+ /*
-+ * this leaf is empty yet:
-+ * we get such a leaf in split/add case
-+ */
-+ return;
-+ }
-+
-+ ext_debug(tree, "binsearch for %d: ", block);
-+
-+ path->p_ext = ex = EXT_FIRST_EXTENT(eh);
-+
-+ r = k = eh->eh_entries;
-+ while (k > 1) {
-+ k = (r - l) / 2;
-+ if (block < ex[l + k].ee_block)
-+ r -= k;
-+ else
-+ l += k;
-+ ext_debug(tree, "%d:%d:%d ", k, l, r);
-+ }
-+
-+ ex += l;
-+ path->p_ext = ex;
-+ ext_debug(tree, " -> %d:%d:%d ", path->p_ext->ee_block,
-+ path->p_ext->ee_start, path->p_ext->ee_len);
-+
-+ while (l++ < r) {
-+ if (block < ex->ee_block)
-+ break;
-+ path->p_ext = ex++;
-+ }
-+ ext_debug(tree, " -> %d:%d:%d\n", path->p_ext->ee_block,
-+ path->p_ext->ee_start, path->p_ext->ee_len);
-+
-+#ifdef CHECK_BINSEARCH
-+ {
-+ struct ext3_extent *chex;
-+
-+ chex = ex = EXT_FIRST_EXTENT(eh);
-+ for (k = 0; k < eh->eh_entries; k++, ex++) {
-+ EXT_ASSERT(k == 0 || ex->ee_block > ex[-1].ee_block);
-+ if (block < ex->ee_block)
-+ break;
-+ chex = ex;
-+ }
-+ EXT_ASSERT(chex == path->p_ext);
-+ }
-+#endif
-+
-+}
-+
-+int ext3_extent_tree_init(handle_t *handle, struct ext3_extents_tree *tree)
-+{
-+ struct ext3_extent_header *eh;
-+
-+ BUG_ON(tree->buffer_len == 0);
-+ ext3_ext_get_access_for_root(handle, tree);
-+ eh = EXT_ROOT_HDR(tree);
-+ eh->eh_depth = 0;
-+ eh->eh_entries = 0;
-+ eh->eh_magic = EXT3_EXT_MAGIC;
-+ eh->eh_max = ext3_ext_space_root(tree);
-+ ext3_ext_mark_root_dirty(handle, tree);
-+ ext3_ext_invalidate_cache(tree);
-+ return 0;
-+}
-+
-+struct ext3_ext_path *
-+ext3_ext_find_extent(struct ext3_extents_tree *tree, int block,
-+ struct ext3_ext_path *path)
-+{
-+ struct ext3_extent_header *eh;
-+ struct buffer_head *bh;
-+ int depth, i, ppos = 0;
-+
-+ EXT_ASSERT(tree);
-+ EXT_ASSERT(tree->inode);
-+ EXT_ASSERT(tree->root);
-+
-+ eh = EXT_ROOT_HDR(tree);
-+ EXT_ASSERT(eh);
-+ i = depth = EXT_DEPTH(tree);
-+ EXT_ASSERT(eh->eh_max);
-+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
-+ EXT_ASSERT(i == 0 || eh->eh_entries > 0);
-+
-+ /* account possible depth increase */
-+ if (!path) {
-+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2),
-+ GFP_NOFS);
-+ if (!path)
-+ return ERR_PTR(-ENOMEM);
-+ }
-+ memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1));
-+ path[0].p_hdr = eh;
-+
-+ /* walk through the tree */
-+ while (i) {
-+ ext_debug(tree, "depth %d: num %d, max %d\n",
-+ ppos, eh->eh_entries, eh->eh_max);
-+ ext3_ext_binsearch_idx(tree, path + ppos, block);
-+ path[ppos].p_block = path[ppos].p_idx->ei_leaf;
-+ path[ppos].p_depth = i;
-+ path[ppos].p_ext = NULL;
-+
-+ bh = sb_bread(tree->inode->i_sb, path[ppos].p_block);
-+ if (!bh) {
-+ ext3_ext_drop_refs(path);
-+ kfree(path);
-+ return ERR_PTR(-EIO);
-+ }
-+ eh = EXT_BLOCK_HDR(bh);
-+ ppos++;
-+ EXT_ASSERT(ppos <= depth);
-+ path[ppos].p_bh = bh;
-+ path[ppos].p_hdr = eh;
-+ i--;
-+ }
-+
-+ path[ppos].p_depth = i;
-+ path[ppos].p_hdr = eh;
-+ path[ppos].p_ext = NULL;
-+
-+ /* find extent */
-+ ext3_ext_binsearch(tree, path + ppos, block);
-+
-+ ext3_ext_show_path(tree, path);
-+
-+ return path;
-+}
-+
-+/*
-+ * insert new index [logical;ptr] into the block at cupr
-+ * it check where to insert: before curp or after curp
-+ */
-+static int ext3_ext_insert_index(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *curp,
-+ int logical, int ptr)
-+{
-+ struct ext3_extent_idx *ix;
-+ int len, err;
-+
-+ if ((err = ext3_ext_get_access(handle, tree, curp)))
-+ return err;
-+
-+ EXT_ASSERT(logical != curp->p_idx->ei_block);
-+ len = EXT_MAX_INDEX(curp->p_hdr) - curp->p_idx;
-+ if (logical > curp->p_idx->ei_block) {
-+ /* insert after */
-+ if (curp->p_idx != EXT_LAST_INDEX(curp->p_hdr)) {
-+ len = (len - 1) * sizeof(struct ext3_extent_idx);
-+ len = len < 0 ? 0 : len;
-+ ext_debug(tree, "insert new index %d after: %d. "
-+ "move %d from 0x%p to 0x%p\n",
-+ logical, ptr, len,
-+ (curp->p_idx + 1), (curp->p_idx + 2));
-+ memmove(curp->p_idx + 2, curp->p_idx + 1, len);
-+ }
-+ ix = curp->p_idx + 1;
-+ } else {
-+ /* insert before */
-+ len = len * sizeof(struct ext3_extent_idx);
-+ len = len < 0 ? 0 : len;
-+ ext_debug(tree, "insert new index %d before: %d. "
-+ "move %d from 0x%p to 0x%p\n",
-+ logical, ptr, len,
-+ curp->p_idx, (curp->p_idx + 1));
-+ memmove(curp->p_idx + 1, curp->p_idx, len);
-+ ix = curp->p_idx;
-+ }
-+
-+ ix->ei_block = logical;
-+ ix->ei_leaf = ptr;
-+ curp->p_hdr->eh_entries++;
-+
-+ EXT_ASSERT(curp->p_hdr->eh_entries <= curp->p_hdr->eh_max);
-+ EXT_ASSERT(ix <= EXT_LAST_INDEX(curp->p_hdr));
-+
-+ err = ext3_ext_dirty(handle, tree, curp);
-+ ext3_std_error(tree->inode->i_sb, err);
-+
-+ return err;
-+}
-+
-+/*
-+ * routine inserts new subtree into the path, using free index entry
-+ * at depth 'at:
-+ * - allocates all needed blocks (new leaf and all intermediate index blocks)
-+ * - makes decision where to split
-+ * - moves remaining extens and index entries (right to the split point)
-+ * into the newly allocated blocks
-+ * - initialize subtree
-+ */
-+static int ext3_ext_split(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext, int at)
-+{
-+ struct buffer_head *bh = NULL;
-+ int depth = EXT_DEPTH(tree);
-+ struct ext3_extent_header *neh;
-+ struct ext3_extent_idx *fidx;
-+ struct ext3_extent *ex;
-+ int i = at, k, m, a;
-+ unsigned long newblock, oldblock, border;
-+ int *ablocks = NULL; /* array of allocated blocks */
-+ int err = 0;
-+
-+ /* make decision: where to split? */
-+ /* FIXME: now desicion is simplest: at current extent */
-+
-+ /* if current leaf will be splitted, then we should use
-+ * border from split point */
-+ EXT_ASSERT(path[depth].p_ext <= EXT_MAX_EXTENT(path[depth].p_hdr));
-+ if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) {
-+ border = path[depth].p_ext[1].ee_block;
-+ ext_debug(tree, "leaf will be splitted."
-+ " next leaf starts at %d\n",
-+ (int)border);
-+ } else {
-+ border = newext->ee_block;
-+ ext_debug(tree, "leaf will be added."
-+ " next leaf starts at %d\n",
-+ (int)border);
-+ }
-+
-+ /*
-+ * if error occurs, then we break processing
-+ * and turn filesystem read-only. so, index won't
-+ * be inserted and tree will be in consistent
-+ * state. next mount will repair buffers too
-+ */
-+
-+ /*
-+ * get array to track all allocated blocks
-+ * we need this to handle errors and free blocks
-+ * upon them
-+ */
-+ ablocks = kmalloc(sizeof(unsigned long) * depth, GFP_NOFS);
-+ if (!ablocks)
-+ return -ENOMEM;
-+ memset(ablocks, 0, sizeof(unsigned long) * depth);
-+
-+ /* allocate all needed blocks */
-+ ext_debug(tree, "allocate %d blocks for indexes/leaf\n", depth - at);
-+ for (a = 0; a < depth - at; a++) {
-+ newblock = ext3_ext_new_block(handle, tree, path, newext, &err);
-+ if (newblock == 0)
-+ goto cleanup;
-+ ablocks[a] = newblock;
-+ }
-+
-+ /* initialize new leaf */
-+ newblock = ablocks[--a];
-+ EXT_ASSERT(newblock);
-+ bh = sb_getblk(tree->inode->i_sb, newblock);
-+ if (!bh) {
-+ err = -EIO;
-+ goto cleanup;
-+ }
-+ lock_buffer(bh);
-+
-+ if ((err = ext3_journal_get_create_access(handle, bh)))
-+ goto cleanup;
-+
-+ neh = EXT_BLOCK_HDR(bh);
-+ neh->eh_entries = 0;
-+ neh->eh_max = ext3_ext_space_block(tree);
-+ neh->eh_magic = EXT3_EXT_MAGIC;
-+ neh->eh_depth = 0;
-+ ex = EXT_FIRST_EXTENT(neh);
-+
-+ /* move remain of path[depth] to the new leaf */
-+ EXT_ASSERT(path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max);
-+ /* start copy from next extent */
-+ /* TODO: we could do it by single memmove */
-+ m = 0;
-+ path[depth].p_ext++;
-+ while (path[depth].p_ext <=
-+ EXT_MAX_EXTENT(path[depth].p_hdr)) {
-+ ext_debug(tree, "move %d:%d:%d in new leaf %lu\n",
-+ path[depth].p_ext->ee_block,
-+ path[depth].p_ext->ee_start,
-+ path[depth].p_ext->ee_len,
-+ newblock);
-+ memmove(ex++, path[depth].p_ext++,
-+ sizeof(struct ext3_extent));
-+ neh->eh_entries++;
-+ m++;
-+ }
-+ mark_buffer_uptodate(bh, 1);
-+ unlock_buffer(bh);
-+
-+ if ((err = ext3_journal_dirty_metadata(handle, bh)))
-+ goto cleanup;
-+ brelse(bh);
-+ bh = NULL;
-+
-+ /* correct old leaf */
-+ if (m) {
-+ if ((err = ext3_ext_get_access(handle, tree, path + depth)))
-+ goto cleanup;
-+ path[depth].p_hdr->eh_entries -= m;
-+ if ((err = ext3_ext_dirty(handle, tree, path + depth)))
-+ goto cleanup;
-+
-+ }
-+
-+ /* create intermediate indexes */
-+ k = depth - at - 1;
-+ EXT_ASSERT(k >= 0);
-+ if (k)
-+ ext_debug(tree, "create %d intermediate indices\n", k);
-+ /* insert new index into current index block */
-+ /* current depth stored in i var */
-+ i = depth - 1;
-+ while (k--) {
-+ oldblock = newblock;
-+ newblock = ablocks[--a];
-+ bh = sb_getblk(tree->inode->i_sb, newblock);
-+ if (!bh) {
-+ err = -EIO;
-+ goto cleanup;
-+ }
-+ lock_buffer(bh);
-+
-+ if ((err = ext3_journal_get_create_access(handle, bh)))
-+ goto cleanup;
-+
-+ neh = EXT_BLOCK_HDR(bh);
-+ neh->eh_entries = 1;
-+ neh->eh_magic = EXT3_EXT_MAGIC;
-+ neh->eh_max = ext3_ext_space_block_idx(tree);
-+ neh->eh_depth = depth - i;
-+ fidx = EXT_FIRST_INDEX(neh);
-+ fidx->ei_block = border;
-+ fidx->ei_leaf = oldblock;
-+
-+ ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n",
-+ i, newblock, border, oldblock);
-+ /* copy indexes */
-+ m = 0;
-+ path[i].p_idx++;
-+
-+ ext_debug(tree, "cur 0x%p, last 0x%p\n", path[i].p_idx,
-+ EXT_MAX_INDEX(path[i].p_hdr));
-+ EXT_ASSERT(EXT_MAX_INDEX(path[i].p_hdr) ==
-+ EXT_LAST_INDEX(path[i].p_hdr));
-+ while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) {
-+ ext_debug(tree, "%d: move %d:%d in new index %lu\n",
-+ i, path[i].p_idx->ei_block,
-+ path[i].p_idx->ei_leaf, newblock);
-+ memmove(++fidx, path[i].p_idx++,
-+ sizeof(struct ext3_extent_idx));
-+ neh->eh_entries++;
-+ EXT_ASSERT(neh->eh_entries <= neh->eh_max);
-+ m++;
-+ }
-+ mark_buffer_uptodate(bh, 1);
-+ unlock_buffer(bh);
-+
-+ if ((err = ext3_journal_dirty_metadata(handle, bh)))
-+ goto cleanup;
-+ brelse(bh);
-+ bh = NULL;
-+
-+ /* correct old index */
-+ if (m) {
-+ err = ext3_ext_get_access(handle, tree, path + i);
-+ if (err)
-+ goto cleanup;
-+ path[i].p_hdr->eh_entries -= m;
-+ err = ext3_ext_dirty(handle, tree, path + i);
-+ if (err)
-+ goto cleanup;
-+ }
-+
-+ i--;
-+ }
-+
-+ /* insert new index */
-+ if (!err)
-+ err = ext3_ext_insert_index(handle, tree, path + at,
-+ border, newblock);
-+
-+cleanup:
-+ if (bh) {
-+ if (buffer_locked(bh))
-+ unlock_buffer(bh);
-+ brelse(bh);
-+ }
-+
-+ if (err) {
-+ /* free all allocated blocks in error case */
-+ for (i = 0; i < depth; i++) {
-+ if (!ablocks[i])
-+ continue;
-+ ext3_free_blocks(handle, tree->inode, ablocks[i], 1);
-+ }
-+ }
-+ kfree(ablocks);
-+
-+ return err;
-+}
-+
-+/*
-+ * routine implements tree growing procedure:
-+ * - allocates new block
-+ * - moves top-level data (index block or leaf) into the new block
-+ * - initialize new top-level, creating index that points to the
-+ * just created block
-+ */
-+static int ext3_ext_grow_indepth(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
-+{
-+ struct ext3_ext_path *curp = path;
-+ struct ext3_extent_header *neh;
-+ struct ext3_extent_idx *fidx;
-+ struct buffer_head *bh;
-+ unsigned long newblock;
-+ int err = 0;
-+
-+ newblock = ext3_ext_new_block(handle, tree, path, newext, &err);
-+ if (newblock == 0)
-+ return err;
-+
-+ bh = sb_getblk(tree->inode->i_sb, newblock);
-+ if (!bh) {
-+ err = -EIO;
-+ ext3_std_error(tree->inode->i_sb, err);
-+ return err;
-+ }
-+ lock_buffer(bh);
-+
-+ if ((err = ext3_journal_get_create_access(handle, bh))) {
-+ unlock_buffer(bh);
-+ goto out;
-+ }
-+
-+ /* move top-level index/leaf into new block */
-+ memmove(bh->b_data, curp->p_hdr, tree->buffer_len);
-+
-+ /* set size of new block */
-+ neh = EXT_BLOCK_HDR(bh);
-+ /* old root could have indexes or leaves
-+ * so calculate eh_max right way */
-+ if (EXT_DEPTH(tree))
-+ neh->eh_max = ext3_ext_space_block_idx(tree);
-+ else
-+ neh->eh_max = ext3_ext_space_block(tree);
-+ neh->eh_magic = EXT3_EXT_MAGIC;
-+ mark_buffer_uptodate(bh, 1);
-+ unlock_buffer(bh);
-+
-+ if ((err = ext3_journal_dirty_metadata(handle, bh)))
-+ goto out;
-+
-+ /* create index in new top-level index: num,max,pointer */
-+ if ((err = ext3_ext_get_access(handle, tree, curp)))
-+ goto out;
-+
-+ curp->p_hdr->eh_magic = EXT3_EXT_MAGIC;
-+ curp->p_hdr->eh_max = ext3_ext_space_root_idx(tree);
-+ curp->p_hdr->eh_entries = 1;
-+ curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr);
-+ /* FIXME: it works, but actually path[0] can be index */
-+ curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block;
-+ curp->p_idx->ei_leaf = newblock;
-+
-+ neh = EXT_ROOT_HDR(tree);
-+ fidx = EXT_FIRST_INDEX(neh);
-+ ext_debug(tree, "new root: num %d(%d), lblock %d, ptr %d\n",
-+ neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf);
-+
-+ neh->eh_depth = path->p_depth + 1;
-+ err = ext3_ext_dirty(handle, tree, curp);
-+out:
-+ brelse(bh);
-+
-+ return err;
-+}
-+
-+/*
-+ * routine finds empty index and adds new leaf. if no free index found
-+ * then it requests in-depth growing
-+ */
-+static int ext3_ext_create_new_leaf(handle_t *handle,
-+ struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
-+{
-+ struct ext3_ext_path *curp;
-+ int depth, i, err = 0;
-+
-+repeat:
-+ i = depth = EXT_DEPTH(tree);
-+
-+ /* walk up to the tree and look for free index entry */
-+ curp = path + depth;
-+ while (i > 0 && !EXT_HAS_FREE_INDEX(curp)) {
-+ i--;
-+ curp--;
-+ }
-+
-+ /* we use already allocated block for index block
-+ * so, subsequent data blocks should be contigoues */
-+ if (EXT_HAS_FREE_INDEX(curp)) {
-+ /* if we found index with free entry, then use that
-+ * entry: create all needed subtree and add new leaf */
-+ err = ext3_ext_split(handle, tree, path, newext, i);
-+
-+ /* refill path */
-+ ext3_ext_drop_refs(path);
-+ path = ext3_ext_find_extent(tree, newext->ee_block, path);
-+ if (IS_ERR(path))
-+ err = PTR_ERR(path);
-+ } else {
-+ /* tree is full, time to grow in depth */
-+ err = ext3_ext_grow_indepth(handle, tree, path, newext);
-+
-+ /* refill path */
-+ ext3_ext_drop_refs(path);
-+ path = ext3_ext_find_extent(tree, newext->ee_block, path);
-+ if (IS_ERR(path))
-+ err = PTR_ERR(path);
-+
-+ /*
-+ * only first (depth 0 -> 1) produces free space
-+ * in all other cases we have to split growed tree
-+ */
-+ depth = EXT_DEPTH(tree);
-+ if (path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max) {
-+ /* now we need split */
-+ goto repeat;
-+ }
-+ }
-+
-+ if (err)
-+ return err;
-+
-+ return 0;
-+}
-+
-+/*
-+ * returns allocated block in subsequent extent or EXT_MAX_BLOCK
-+ * NOTE: it consider block number from index entry as
-+ * allocated block. thus, index entries have to be consistent
-+ * with leafs
-+ */
-+static unsigned long
-+ext3_ext_next_allocated_block(struct ext3_ext_path *path)
-+{
-+ int depth;
-+
-+ EXT_ASSERT(path != NULL);
-+ depth = path->p_depth;
-+
-+ if (depth == 0 && path->p_ext == NULL)
-+ return EXT_MAX_BLOCK;
-+
-+ /* FIXME: what if index isn't full ?! */
-+ while (depth >= 0) {
-+ if (depth == path->p_depth) {
-+ /* leaf */
-+ if (path[depth].p_ext !=
-+ EXT_LAST_EXTENT(path[depth].p_hdr))
-+ return path[depth].p_ext[1].ee_block;
-+ } else {
-+ /* index */
-+ if (path[depth].p_idx !=
-+ EXT_LAST_INDEX(path[depth].p_hdr))
-+ return path[depth].p_idx[1].ei_block;
-+ }
-+ depth--;
-+ }
-+
-+ return EXT_MAX_BLOCK;
-+}
-+
-+/*
-+ * returns first allocated block from next leaf or EXT_MAX_BLOCK
-+ */
-+static unsigned ext3_ext_next_leaf_block(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
-+{
-+ int depth;
-+
-+ EXT_ASSERT(path != NULL);
-+ depth = path->p_depth;
-+
-+ /* zero-tree has no leaf blocks at all */
-+ if (depth == 0)
-+ return EXT_MAX_BLOCK;
-+
-+ /* go to index block */
-+ depth--;
-+
-+ while (depth >= 0) {
-+ if (path[depth].p_idx !=
-+ EXT_LAST_INDEX(path[depth].p_hdr))
-+ return path[depth].p_idx[1].ei_block;
-+ depth--;
-+ }
-+
-+ return EXT_MAX_BLOCK;
-+}
-+
-+/*
-+ * if leaf gets modified and modified extent is first in the leaf
-+ * then we have to correct all indexes above
-+ * TODO: do we need to correct tree in all cases?
-+ */
-+int ext3_ext_correct_indexes(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
-+{
-+ struct ext3_extent_header *eh;
-+ int depth = EXT_DEPTH(tree);
-+ struct ext3_extent *ex;
-+ unsigned long border;
-+ int k, err = 0;
-+
-+ eh = path[depth].p_hdr;
-+ ex = path[depth].p_ext;
-+ EXT_ASSERT(ex);
-+ EXT_ASSERT(eh);
-+
-+ if (depth == 0) {
-+ /* there is no tree at all */
-+ return 0;
-+ }
-+
-+ if (ex != EXT_FIRST_EXTENT(eh)) {
-+ /* we correct tree if first leaf got modified only */
-+ return 0;
-+ }
-+
-+ /*
-+ * TODO: we need correction if border is smaller then current one
-+ */
-+ k = depth - 1;
-+ border = path[depth].p_ext->ee_block;
-+ if ((err = ext3_ext_get_access(handle, tree, path + k)))
-+ return err;
-+ path[k].p_idx->ei_block = border;
-+ if ((err = ext3_ext_dirty(handle, tree, path + k)))
-+ return err;
-+
-+ while (k--) {
-+ /* change all left-side indexes */
-+ if (path[k+1].p_idx != EXT_FIRST_INDEX(path[k+1].p_hdr))
-+ break;
-+ if ((err = ext3_ext_get_access(handle, tree, path + k)))
-+ break;
-+ path[k].p_idx->ei_block = border;
-+ if ((err = ext3_ext_dirty(handle, tree, path + k)))
-+ break;
-+ }
-+
-+ return err;
-+}
-+
-+static int inline
-+ext3_can_extents_be_merged(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex1,
-+ struct ext3_extent *ex2)
-+{
-+ if (ex1->ee_block + ex1->ee_len != ex2->ee_block)
-+ return 0;
-+
-+#ifdef AGRESSIVE_TEST
-+ if (ex1->ee_len >= 4)
-+ return 0;
-+#endif
-+
-+ if (!tree->ops->mergable)
-+ return 1;
-+
-+ return tree->ops->mergable(ex1, ex2);
-+}
-+
-+/*
-+ * this routine tries to merge requsted extent into the existing
-+ * extent or inserts requested extent as new one into the tree,
-+ * creating new leaf in no-space case
-+ */
-+int ext3_ext_insert_extent(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newext)
-+{
-+ struct ext3_extent_header * eh;
-+ struct ext3_extent *ex, *fex;
-+ struct ext3_extent *nearex; /* nearest extent */
-+ struct ext3_ext_path *npath = NULL;
-+ int depth, len, err, next;
-+
-+ EXT_ASSERT(newext->ee_len > 0);
-+ EXT_ASSERT(newext->ee_len < EXT_CACHE_MARK);
-+ depth = EXT_DEPTH(tree);
-+ ex = path[depth].p_ext;
-+ EXT_ASSERT(path[depth].p_hdr);
-+
-+ /* try to insert block into found extent and return */
-+ if (ex && ext3_can_extents_be_merged(tree, ex, newext)) {
-+ ext_debug(tree, "append %d block to %d:%d (from %d)\n",
-+ newext->ee_len, ex->ee_block, ex->ee_len,
-+ ex->ee_start);
-+ if ((err = ext3_ext_get_access(handle, tree, path + depth)))
-+ return err;
-+ ex->ee_len += newext->ee_len;
-+ eh = path[depth].p_hdr;
-+ nearex = ex;
-+ goto merge;
-+ }
-+
-+repeat:
-+ depth = EXT_DEPTH(tree);
-+ eh = path[depth].p_hdr;
-+ if (eh->eh_entries < eh->eh_max)
-+ goto has_space;
-+
-+ /* probably next leaf has space for us? */
-+ fex = EXT_LAST_EXTENT(eh);
-+ next = ext3_ext_next_leaf_block(tree, path);
-+ if (newext->ee_block > fex->ee_block && next != EXT_MAX_BLOCK) {
-+ ext_debug(tree, "next leaf block - %d\n", next);
-+ EXT_ASSERT(!npath);
-+ npath = ext3_ext_find_extent(tree, next, NULL);
-+ if (IS_ERR(npath))
-+ return PTR_ERR(npath);
-+ EXT_ASSERT(npath->p_depth == path->p_depth);
-+ eh = npath[depth].p_hdr;
-+ if (eh->eh_entries < eh->eh_max) {
-+ ext_debug(tree, "next leaf isnt full(%d)\n",
-+ eh->eh_entries);
-+ path = npath;
-+ goto repeat;
-+ }
-+ ext_debug(tree, "next leaf hasno free space(%d,%d)\n",
-+ eh->eh_entries, eh->eh_max);
-+ }
-+
-+ /*
-+ * there is no free space in found leaf
-+ * we're gonna add new leaf in the tree
-+ */
-+ err = ext3_ext_create_new_leaf(handle, tree, path, newext);
-+ if (err)
-+ goto cleanup;
-+ depth = EXT_DEPTH(tree);
-+ eh = path[depth].p_hdr;
-+
-+has_space:
-+ nearex = path[depth].p_ext;
-+
-+ if ((err = ext3_ext_get_access(handle, tree, path + depth)))
-+ goto cleanup;
-+
-+ if (!nearex) {
-+ /* there is no extent in this leaf, create first one */
-+ ext_debug(tree, "first extent in the leaf: %d:%d:%d\n",
-+ newext->ee_block, newext->ee_start,
-+ newext->ee_len);
-+ path[depth].p_ext = EXT_FIRST_EXTENT(eh);
-+ } else if (newext->ee_block > nearex->ee_block) {
-+ EXT_ASSERT(newext->ee_block != nearex->ee_block);
-+ if (nearex != EXT_LAST_EXTENT(eh)) {
-+ len = EXT_MAX_EXTENT(eh) - nearex;
-+ len = (len - 1) * sizeof(struct ext3_extent);
-+ len = len < 0 ? 0 : len;
-+ ext_debug(tree, "insert %d:%d:%d after: nearest 0x%p, "
-+ "move %d from 0x%p to 0x%p\n",
-+ newext->ee_block, newext->ee_start,
-+ newext->ee_len,
-+ nearex, len, nearex + 1, nearex + 2);
-+ memmove(nearex + 2, nearex + 1, len);
-+ }
-+ path[depth].p_ext = nearex + 1;
-+ } else {
-+ EXT_ASSERT(newext->ee_block != nearex->ee_block);
-+ len = (EXT_MAX_EXTENT(eh) - nearex) * sizeof(struct ext3_extent);
-+ len = len < 0 ? 0 : len;
-+ ext_debug(tree, "insert %d:%d:%d before: nearest 0x%p, "
-+ "move %d from 0x%p to 0x%p\n",
-+ newext->ee_block, newext->ee_start, newext->ee_len,
-+ nearex, len, nearex + 1, nearex + 2);
-+ memmove(nearex + 1, nearex, len);
-+ path[depth].p_ext = nearex;
-+ }
-+
-+ eh->eh_entries++;
-+ nearex = path[depth].p_ext;
-+ nearex->ee_block = newext->ee_block;
-+ nearex->ee_start = newext->ee_start;
-+ nearex->ee_len = newext->ee_len;
-+ /* FIXME: support for large fs */
-+ nearex->ee_start_hi = 0;
-+
-+merge:
-+ /* try to merge extents to the right */
-+ while (nearex < EXT_LAST_EXTENT(eh)) {
-+ if (!ext3_can_extents_be_merged(tree, nearex, nearex + 1))
-+ break;
-+ /* merge with next extent! */
-+ nearex->ee_len += nearex[1].ee_len;
-+ if (nearex + 1 < EXT_LAST_EXTENT(eh)) {
-+ len = (EXT_LAST_EXTENT(eh) - nearex - 1)
-+ * sizeof(struct ext3_extent);
-+ memmove(nearex + 1, nearex + 2, len);
-+ }
-+ eh->eh_entries--;
-+ EXT_ASSERT(eh->eh_entries > 0);
-+ }
-+
-+ /* try to merge extents to the left */
-+
-+ /* time to correct all indexes above */
-+ err = ext3_ext_correct_indexes(handle, tree, path);
-+ if (err)
-+ goto cleanup;
-+
-+ err = ext3_ext_dirty(handle, tree, path + depth);
-+
-+cleanup:
-+ if (npath) {
-+ ext3_ext_drop_refs(npath);
-+ kfree(npath);
-+ }
-+ ext3_ext_tree_changed(tree);
-+ ext3_ext_invalidate_cache(tree);
-+ return err;
-+}
-+
-+int ext3_ext_walk_space(struct ext3_extents_tree *tree, unsigned long block,
-+ unsigned long num, ext_prepare_callback func)
-+{
-+ struct ext3_ext_path *path = NULL;
-+ struct ext3_extent *ex, cbex;
-+ unsigned long next, start = 0, end = 0;
-+ unsigned long last = block + num;
-+ int depth, exists, err = 0;
-+
-+ EXT_ASSERT(tree);
-+ EXT_ASSERT(func);
-+ EXT_ASSERT(tree->inode);
-+ EXT_ASSERT(tree->root);
-+
-+ while (block < last && block != EXT_MAX_BLOCK) {
-+ num = last - block;
-+ /* find extent for this block */
-+ path = ext3_ext_find_extent(tree, block, path);
-+ if (IS_ERR(path)) {
-+ err = PTR_ERR(path);
-+ path = NULL;
-+ break;
-+ }
-+
-+ depth = EXT_DEPTH(tree);
-+ EXT_ASSERT(path[depth].p_hdr);
-+ ex = path[depth].p_ext;
-+ next = ext3_ext_next_allocated_block(path);
-+
-+ exists = 0;
-+ if (!ex) {
-+ /* there is no extent yet, so try to allocate
-+ * all requested space */
-+ start = block;
-+ end = block + num;
-+ } else if (ex->ee_block > block) {
-+ /* need to allocate space before found extent */
-+ start = block;
-+ end = ex->ee_block;
-+ if (block + num < end)
-+ end = block + num;
-+ } else if (block >= ex->ee_block + ex->ee_len) {
-+ /* need to allocate space after found extent */
-+ start = block;
-+ end = block + num;
-+ if (end >= next)
-+ end = next;
-+ } else if (block >= ex->ee_block) {
-+ /*
-+ * some part of requested space is covered
-+ * by found extent
-+ */
-+ start = block;
-+ end = ex->ee_block + ex->ee_len;
-+ if (block + num < end)
-+ end = block + num;
-+ exists = 1;
-+ } else {
-+ BUG();
-+ }
-+ EXT_ASSERT(end > start);
-+
-+ if (!exists) {
-+ cbex.ee_block = start;
-+ cbex.ee_len = end - start;
-+ cbex.ee_start = 0;
-+ } else
-+ cbex = *ex;
-+
-+ EXT_ASSERT(path[depth].p_hdr);
-+ err = func(tree, path, &cbex, exists);
-+ ext3_ext_drop_refs(path);
-+
-+ if (err < 0)
-+ break;
-+ if (err == EXT_REPEAT)
-+ continue;
-+ else if (err == EXT_BREAK) {
-+ err = 0;
-+ break;
-+ }
-+
-+ if (EXT_DEPTH(tree) != depth) {
-+ /* depth was changed. we have to realloc path */
-+ kfree(path);
-+ path = NULL;
-+ }
-+
-+ block = cbex.ee_block + cbex.ee_len;
-+ }
-+
-+ if (path) {
-+ ext3_ext_drop_refs(path);
-+ kfree(path);
-+ }
-+
-+ return err;
-+}
-+
-+static inline void
-+ext3_ext_put_in_cache(struct ext3_extents_tree *tree, struct ext3_extent *ex)
-+{
-+ if (tree->cex) {
-+ EXT_ASSERT(ex);
-+ EXT_ASSERT(ex->ee_len);
-+ tree->cex->ee_block = ex->ee_block;
-+ tree->cex->ee_start = ex->ee_start;
-+ tree->cex->ee_len = ex->ee_len;
-+ }
-+}
-+
-+/*
-+ * this routine calculate boundaries of the gap requested block fits into
-+ * and cache this gap
-+ */
-+static inline void
-+ext3_ext_put_gap_in_cache(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ unsigned long block)
-+{
-+ int depth = EXT_DEPTH(tree);
-+ struct ext3_extent *ex, gex;
-+
-+ if (!tree->cex)
-+ return;
-+
-+ ex = path[depth].p_ext;
-+ if (ex == NULL) {
-+ /* there is no extent yet, so gap is [0;-] */
-+ gex.ee_block = 0;
-+ gex.ee_len = EXT_CACHE_MARK;
-+ ext_debug(tree, "cache gap(whole file):");
-+ } else if (block < ex->ee_block) {
-+ gex.ee_block = block;
-+ gex.ee_len = ex->ee_block - block;
-+ ext_debug(tree, "cache gap(before): %lu [%lu:%lu]",
-+ (unsigned long) block,
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len);
-+ } else if (block >= ex->ee_block + ex->ee_len) {
-+ gex.ee_block = ex->ee_block + ex->ee_len;
-+ gex.ee_len = ext3_ext_next_allocated_block(path);
-+ ext_debug(tree, "cache gap(after): [%lu:%lu] %lu",
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len,
-+ (unsigned long) block);
-+ EXT_ASSERT(gex.ee_len > gex.ee_block);
-+ gex.ee_len = gex.ee_len - gex.ee_block;
-+ } else {
-+ BUG();
-+ }
-+
-+ ext_debug(tree, " -> %lu:%lu\n", (unsigned long) gex.ee_block,
-+ (unsigned long) gex.ee_len);
-+ gex.ee_start = EXT_CACHE_MARK;
-+ ext3_ext_put_in_cache(tree, &gex);
-+}
-+
-+static inline int
-+ext3_ext_in_cache(struct ext3_extents_tree *tree, unsigned long block,
-+ struct ext3_extent *ex)
-+{
-+ struct ext3_extent *cex = tree->cex;
-+
-+ /* is there cache storage at all? */
-+ if (!cex)
-+ return 0;
-+
-+ /* has cache valid data? */
-+ if (cex->ee_len == 0)
-+ return 0;
-+
-+ if (block >= cex->ee_block && block < cex->ee_block + cex->ee_len) {
-+ ex->ee_block = cex->ee_block;
-+ ex->ee_start = cex->ee_start;
-+ ex->ee_len = cex->ee_len;
-+ ext_debug(tree, "%lu cached by %lu:%lu:%lu\n",
-+ (unsigned long) block,
-+ (unsigned long) ex->ee_block,
-+ (unsigned long) ex->ee_len,
-+ (unsigned long) ex->ee_start);
-+ return 1;
-+ }
-+
-+ /* not in cache */
-+ return 0;
-+}
-+
-+/*
-+ * routine removes index from the index block
-+ * it's used in truncate case only. thus all requests are for
-+ * last index in the block only
-+ */
-+int ext3_ext_rm_idx(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
-+{
-+ struct buffer_head *bh;
-+ int err;
-+
-+ /* free index block */
-+ path--;
-+ EXT_ASSERT(path->p_hdr->eh_entries);
-+ if ((err = ext3_ext_get_access(handle, tree, path)))
-+ return err;
-+ path->p_hdr->eh_entries--;
-+ if ((err = ext3_ext_dirty(handle, tree, path)))
-+ return err;
-+ ext_debug(tree, "index is empty, remove it, free block %d\n",
-+ path->p_idx->ei_leaf);
-+ bh = sb_get_hash_table(tree->inode->i_sb, path->p_idx->ei_leaf);
-+ ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf);
-+ ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1);
-+ return err;
-+}
-+
-+int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path)
-+{
-+ int depth = EXT_DEPTH(tree);
-+ int needed;
-+
-+ if (path) {
-+ /* probably there is space in leaf? */
-+ if (path[depth].p_hdr->eh_entries < path[depth].p_hdr->eh_max)
-+ return 1;
-+ }
-+
-+ /*
-+ * the worste case we're expecting is creation of the
-+ * new root (growing in depth) with index splitting
-+ * for splitting we have to consider depth + 1 because
-+ * previous growing could increase it
-+ */
-+ depth = depth + 1;
-+
-+ /*
-+ * growing in depth:
-+ * block allocation + new root + old root
-+ */
-+ needed = EXT3_ALLOC_NEEDED + 2;
-+
-+ /* index split. we may need:
-+ * allocate intermediate indexes and new leaf
-+ * change two blocks at each level, but root
-+ * modify root block (inode)
-+ */
-+ needed += (depth * EXT3_ALLOC_NEEDED) + (2 * depth) + 1;
-+
-+ return needed;
-+}
-+
-+static int
-+ext3_ext_split_for_rm(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, unsigned long start,
-+ unsigned long end)
-+{
-+ struct ext3_extent *ex, tex;
-+ struct ext3_ext_path *npath;
-+ int depth, creds, err;
-+
-+ depth = EXT_DEPTH(tree);
-+ ex = path[depth].p_ext;
-+ EXT_ASSERT(ex);
-+ EXT_ASSERT(end < ex->ee_block + ex->ee_len - 1);
-+ EXT_ASSERT(ex->ee_block < start);
-+
-+ /* calculate tail extent */
-+ tex.ee_block = end + 1;
-+ EXT_ASSERT(tex.ee_block < ex->ee_block + ex->ee_len);
-+ tex.ee_len = ex->ee_block + ex->ee_len - tex.ee_block;
-+
-+ creds = ext3_ext_calc_credits_for_insert(tree, path);
-+ handle = ext3_ext_journal_restart(handle, creds);
-+ if (IS_ERR(handle))
-+ return PTR_ERR(handle);
-+
-+ /* calculate head extent. use primary extent */
-+ err = ext3_ext_get_access(handle, tree, path + depth);
-+ if (err)
-+ return err;
-+ ex->ee_len = start - ex->ee_block;
-+ err = ext3_ext_dirty(handle, tree, path + depth);
-+ if (err)
-+ return err;
-+
-+ /* FIXME: some callback to free underlying resource
-+ * and correct ee_start? */
-+ ext_debug(tree, "split extent: head %u:%u, tail %u:%u\n",
-+ ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len);
-+
-+ npath = ext3_ext_find_extent(tree, ex->ee_block, NULL);
-+ if (IS_ERR(npath))
-+ return PTR_ERR(npath);
-+ depth = EXT_DEPTH(tree);
-+ EXT_ASSERT(npath[depth].p_ext->ee_block == ex->ee_block);
-+ EXT_ASSERT(npath[depth].p_ext->ee_len == ex->ee_len);
-+
-+ err = ext3_ext_insert_extent(handle, tree, npath, &tex);
-+ ext3_ext_drop_refs(npath);
-+ kfree(npath);
-+
-+ return err;
-+
-+}
-+
-+static int
-+ext3_ext_rm_leaf(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path, unsigned long start,
-+ unsigned long end)
-+{
-+ struct ext3_extent *ex, *fu = NULL, *lu, *le;
-+ int err = 0, correct_index = 0;
-+ int depth = EXT_DEPTH(tree), credits;
-+ struct ext3_extent_header *eh;
-+ unsigned a, b, block, num;
-+
-+ ext_debug(tree, "remove [%lu:%lu] in leaf\n", start, end);
-+ if (!path[depth].p_hdr)
-+ path[depth].p_hdr = EXT_BLOCK_HDR(path[depth].p_bh);
-+ eh = path[depth].p_hdr;
-+ EXT_ASSERT(eh);
-+ EXT_ASSERT(eh->eh_entries <= eh->eh_max);
-+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
-+
-+ /* find where to start removing */
-+ le = ex = EXT_LAST_EXTENT(eh);
-+ while (ex != EXT_FIRST_EXTENT(eh)) {
-+ if (ex->ee_block <= end)
-+ break;
-+ ex--;
-+ }
-+
-+ if (start > ex->ee_block && end < ex->ee_block + ex->ee_len - 1) {
-+ /* removal of internal part of the extent requested
-+ * tail and head must be placed in different extent
-+ * so, we have to insert one more extent */
-+ path[depth].p_ext = ex;
-+ return ext3_ext_split_for_rm(handle, tree, path, start, end);
-+ }
-+
-+ lu = ex;
-+ while (ex >= EXT_FIRST_EXTENT(eh) &&
-+ ex->ee_block + ex->ee_len > start) {
-+ ext_debug(tree, "remove ext %u:%u\n", ex->ee_block, ex->ee_len);
-+ path[depth].p_ext = ex;
-+
-+ a = ex->ee_block > start ? ex->ee_block : start;
-+ b = ex->ee_block + ex->ee_len - 1 < end ?
-+ ex->ee_block + ex->ee_len - 1 : end;
-+
-+ ext_debug(tree, " border %u:%u\n", a, b);
-+
-+ if (a != ex->ee_block && b != ex->ee_block + ex->ee_len - 1) {
-+ block = 0;
-+ num = 0;
-+ BUG();
-+ } else if (a != ex->ee_block) {
-+ /* remove tail of the extent */
-+ block = ex->ee_block;
-+ num = a - block;
-+ } else if (b != ex->ee_block + ex->ee_len - 1) {
-+ /* remove head of the extent */
-+ block = a;
-+ num = b - a;
-+ } else {
-+ /* remove whole extent: excelent! */
-+ block = ex->ee_block;
-+ num = 0;
-+ EXT_ASSERT(a == ex->ee_block &&
-+ b == ex->ee_block + ex->ee_len - 1);
-+ }
-+
-+ if (ex == EXT_FIRST_EXTENT(eh))
-+ correct_index = 1;
-+
-+ credits = 1;
-+ if (correct_index)
-+ credits += (EXT_DEPTH(tree) * EXT3_ALLOC_NEEDED) + 1;
-+ if (tree->ops->remove_extent_credits)
-+ credits+=tree->ops->remove_extent_credits(tree,ex,a,b);
-+
-+ handle = ext3_ext_journal_restart(handle, credits);
-+ if (IS_ERR(handle)) {
-+ err = PTR_ERR(handle);
-+ goto out;
-+ }
-+
-+ err = ext3_ext_get_access(handle, tree, path + depth);
-+ if (err)
-+ goto out;
-+
-+ if (tree->ops->remove_extent)
-+ err = tree->ops->remove_extent(tree, ex, a, b);
-+ if (err)
-+ goto out;
-+
-+ if (num == 0) {
-+ /* this extent is removed entirely mark slot unused */
-+ ex->ee_start = 0;
-+ eh->eh_entries--;
-+ fu = ex;
-+ }
-+
-+ ex->ee_block = block;
-+ ex->ee_len = num;
-+
-+ err = ext3_ext_dirty(handle, tree, path + depth);
-+ if (err)
-+ goto out;
-+
-+ ext_debug(tree, "new extent: %u:%u:%u\n",
-+ ex->ee_block, ex->ee_len, ex->ee_start);
-+ ex--;
-+ }
-+
-+ if (fu) {
-+ /* reuse unused slots */
-+ while (lu < le) {
-+ if (lu->ee_start) {
-+ *fu = *lu;
-+ lu->ee_start = 0;
-+ fu++;
-+ }
-+ lu++;
-+ }
-+ }
-+
-+ if (correct_index && eh->eh_entries)
-+ err = ext3_ext_correct_indexes(handle, tree, path);
-+
-+ /* if this leaf is free, then we should
-+ * remove it from index block above */
-+ if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL)
-+ err = ext3_ext_rm_idx(handle, tree, path + depth);
-+
-+out:
-+ return err;
-+}
-+
-+
-+static struct ext3_extent_idx *
-+ext3_ext_last_covered(struct ext3_extent_header *hdr, unsigned long block)
-+{
-+ struct ext3_extent_idx *ix;
-+
-+ ix = EXT_LAST_INDEX(hdr);
-+ while (ix != EXT_FIRST_INDEX(hdr)) {
-+ if (ix->ei_block <= block)
-+ break;
-+ ix--;
-+ }
-+ return ix;
-+}
-+
-+/*
-+ * returns 1 if current index have to be freed (even partial)
-+ */
-+static int inline
-+ext3_ext_more_to_rm(struct ext3_ext_path *path)
-+{
-+ EXT_ASSERT(path->p_idx);
-+
-+ if (path->p_idx < EXT_FIRST_INDEX(path->p_hdr))
-+ return 0;
-+
-+ /*
-+ * if truncate on deeper level happened it it wasn't partial
-+ * so we have to consider current index for truncation
-+ */
-+ if (path->p_hdr->eh_entries == path->p_block)
-+ return 0;
-+ return 1;
-+}
-+
-+int ext3_ext_remove_space(struct ext3_extents_tree *tree,
-+ unsigned long start, unsigned long end)
-+{
-+ struct inode *inode = tree->inode;
-+ struct super_block *sb = inode->i_sb;
-+ int depth = EXT_DEPTH(tree);
-+ struct ext3_ext_path *path;
-+ handle_t *handle;
-+ int i = 0, err = 0;
-+
-+ ext_debug(tree, "space to be removed: %lu:%lu\n", start, end);
-+
-+ /* probably first extent we're gonna free will be last in block */
-+ handle = ext3_journal_start(inode, depth + 1);
-+ if (IS_ERR(handle))
-+ return PTR_ERR(handle);
-+
-+ ext3_ext_invalidate_cache(tree);
-+
-+ /*
-+ * we start scanning from right side freeing all the blocks
-+ * after i_size and walking into the deep
-+ */
-+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 1), GFP_KERNEL);
-+ if (IS_ERR(path)) {
-+ ext3_error(sb, "ext3_ext_remove_space",
-+ "Can't allocate path array");
-+ ext3_journal_stop(handle, inode);
-+ return -ENOMEM;
-+ }
-+ memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1));
-+ path[i].p_hdr = EXT_ROOT_HDR(tree);
-+
-+ while (i >= 0 && err == 0) {
-+ if (i == depth) {
-+ /* this is leaf block */
-+ err = ext3_ext_rm_leaf(handle, tree, path, start, end);
-+ /* root level have p_bh == NULL, brelse() eats this */
-+ brelse(path[i].p_bh);
-+ i--;
-+ continue;
-+ }
-+
-+ /* this is index block */
-+ if (!path[i].p_hdr) {
-+ ext_debug(tree, "initialize header\n");
-+ path[i].p_hdr = EXT_BLOCK_HDR(path[i].p_bh);
-+ }
-+
-+ EXT_ASSERT(path[i].p_hdr->eh_entries <= path[i].p_hdr->eh_max);
-+ EXT_ASSERT(path[i].p_hdr->eh_magic == EXT3_EXT_MAGIC);
-+
-+ if (!path[i].p_idx) {
-+ /* this level hasn't touched yet */
-+ path[i].p_idx =
-+ ext3_ext_last_covered(path[i].p_hdr, end);
-+ path[i].p_block = path[i].p_hdr->eh_entries + 1;
-+ ext_debug(tree, "init index ptr: hdr 0x%p, num %d\n",
-+ path[i].p_hdr, path[i].p_hdr->eh_entries);
-+ } else {
-+ /* we've already was here, see at next index */
-+ path[i].p_idx--;
-+ }
-+
-+ ext_debug(tree, "level %d - index, first 0x%p, cur 0x%p\n",
-+ i, EXT_FIRST_INDEX(path[i].p_hdr),
-+ path[i].p_idx);
-+ if (ext3_ext_more_to_rm(path + i)) {
-+ /* go to the next level */
-+ ext_debug(tree, "move to level %d (block %d)\n",
-+ i + 1, path[i].p_idx->ei_leaf);
-+ memset(path + i + 1, 0, sizeof(*path));
-+ path[i+1].p_bh = sb_bread(sb, path[i].p_idx->ei_leaf);
-+ if (!path[i+1].p_bh) {
-+ /* should we reset i_size? */
-+ err = -EIO;
-+ break;
-+ }
-+ /* put actual number of indexes to know is this
-+ * number got changed at the next iteration */
-+ path[i].p_block = path[i].p_hdr->eh_entries;
-+ i++;
-+ } else {
-+ /* we finish processing this index, go up */
-+ if (path[i].p_hdr->eh_entries == 0 && i > 0) {
-+ /* index is empty, remove it
-+ * handle must be already prepared by the
-+ * truncatei_leaf() */
-+ err = ext3_ext_rm_idx(handle, tree, path + i);
-+ }
-+ /* root level have p_bh == NULL, brelse() eats this */
-+ brelse(path[i].p_bh);
-+ i--;
-+ ext_debug(tree, "return to level %d\n", i);
-+ }
-+ }
-+
-+ /* TODO: flexible tree reduction should be here */
-+ if (path->p_hdr->eh_entries == 0) {
-+ /*
-+ * truncate to zero freed all the tree
-+ * so, we need to correct eh_depth
-+ */
-+ err = ext3_ext_get_access(handle, tree, path);
-+ if (err == 0) {
-+ EXT_ROOT_HDR(tree)->eh_depth = 0;
-+ EXT_ROOT_HDR(tree)->eh_max = ext3_ext_space_root(tree);
-+ err = ext3_ext_dirty(handle, tree, path);
-+ }
-+ }
-+ ext3_ext_tree_changed(tree);
-+
-+ kfree(path);
-+ ext3_journal_stop(handle, inode);
-+
-+ return err;
-+}
-+
-+/*
-+ * called at mount time
-+ */
-+void ext3_ext_init(struct super_block *sb)
-+{
-+ /*
-+ * possible initialization would be here
-+ */
-+
-+ if (test_opt(sb, EXTENTS)) {
-+ printk("EXT3-fs: file extents enabled");
-+#ifdef AGRESSIVE_TEST
-+ printk(", agressive tests");
-+#endif
-+#ifdef CHECK_BINSEARCH
-+ printk(", check binsearch");
-+#endif
-+ printk("\n");
-+ }
-+}
-+
-+/*
-+ * called at umount time
-+ */
-+void ext3_ext_release(struct super_block *sb)
-+{
-+}
-+
-+/************************************************************************
-+ * VFS related routines
-+ ************************************************************************/
-+
-+static int ext3_get_inode_write_access(handle_t *handle, void *buffer)
-+{
-+ /* we use in-core data, not bh */
-+ return 0;
-+}
-+
-+static int ext3_mark_buffer_dirty(handle_t *handle, void *buffer)
-+{
-+ struct inode *inode = buffer;
-+ return ext3_mark_inode_dirty(handle, inode);
-+}
-+
-+static int ext3_ext_mergable(struct ext3_extent *ex1,
-+ struct ext3_extent *ex2)
-+{
-+ /* FIXME: support for large fs */
-+ if (ex1->ee_start + ex1->ee_len == ex2->ee_start)
-+ return 1;
-+ return 0;
-+}
-+
-+static int
-+ext3_remove_blocks_credits(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex,
-+ unsigned long from, unsigned long to)
-+{
-+ int needed;
-+
-+ /* at present, extent can't cross block group */;
-+ needed = 4; /* bitmap + group desc + sb + inode */
-+
-+#ifdef CONFIG_QUOTA
-+ needed += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS;
-+#endif
-+ return needed;
-+}
-+
-+static int
-+ext3_remove_blocks(struct ext3_extents_tree *tree,
-+ struct ext3_extent *ex,
-+ unsigned long from, unsigned long to)
-+{
-+ int needed = ext3_remove_blocks_credits(tree, ex, from, to);
-+ handle_t *handle = ext3_journal_start(tree->inode, needed);
-+ struct buffer_head *bh;
-+ int i;
-+
-+ if (IS_ERR(handle))
-+ return PTR_ERR(handle);
-+ if (from >= ex->ee_block && to == ex->ee_block + ex->ee_len - 1) {
-+ /* tail removal */
-+ unsigned long num, start;
-+ num = ex->ee_block + ex->ee_len - from;
-+ start = ex->ee_start + ex->ee_len - num;
-+ ext_debug(tree, "free last %lu blocks starting %lu\n",
-+ num, start);
-+ for (i = 0; i < num; i++) {
-+ bh = sb_get_hash_table(tree->inode->i_sb, start + i);
-+ ext3_forget(handle, 0, tree->inode, bh, start + i);
-+ }
-+ ext3_free_blocks(handle, tree->inode, start, num);
-+ } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) {
-+ printk("strange request: removal %lu-%lu from %u:%u\n",
-+ from, to, ex->ee_block, ex->ee_len);
-+ } else {
-+ printk("strange request: removal(2) %lu-%lu from %u:%u\n",
-+ from, to, ex->ee_block, ex->ee_len);
-+ }
-+ ext3_journal_stop(handle, tree->inode);
-+ return 0;
-+}
-+
-+int ext3_ext_find_goal(struct inode *inode, struct ext3_ext_path *path,
-+ unsigned long block)
-+{
-+ struct ext3_inode_info *ei = EXT3_I(inode);
-+ unsigned long bg_start;
-+ unsigned long colour;
-+ int depth;
-+
-+ if (path) {
-+ struct ext3_extent *ex;
-+ depth = path->p_depth;
-+
-+ /* try to predict block placement */
-+ if ((ex = path[depth].p_ext))
-+ return ex->ee_start + (block - ex->ee_block);
-+
-+ /* it looks index is empty
-+ * try to find starting from index itself */
-+ if (path[depth].p_bh)
-+ return path[depth].p_bh->b_blocknr;
-+ }
-+
-+ /* OK. use inode's group */
-+ bg_start = (ei->i_block_group * EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
-+ le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
-+ colour = (current->pid % 16) *
-+ (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16);
-+ return bg_start + colour + block;
-+}
-+
-+static int ext3_new_block_cb(handle_t *handle, struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *ex, int *err)
-+{
-+ struct inode *inode = tree->inode;
-+ int newblock, goal;
-+
-+ EXT_ASSERT(path);
-+ EXT_ASSERT(ex);
-+ EXT_ASSERT(ex->ee_start);
-+ EXT_ASSERT(ex->ee_len);
-+
-+ /* reuse block from the extent to order data/metadata */
-+ newblock = ex->ee_start++;
-+ ex->ee_len--;
-+ if (ex->ee_len == 0) {
-+ ex->ee_len = 1;
-+ /* allocate new block for the extent */
-+ goal = ext3_ext_find_goal(inode, path, ex->ee_block);
-+ ex->ee_start = ext3_new_block(handle, inode, goal, 0, 0, err);
-+ if (ex->ee_start == 0) {
-+ /* error occured: restore old extent */
-+ ex->ee_start = newblock;
-+ return 0;
-+ }
-+ }
-+ return newblock;
-+}
-+
-+static struct ext3_extents_helpers ext3_blockmap_helpers = {
-+ .get_write_access = ext3_get_inode_write_access,
-+ .mark_buffer_dirty = ext3_mark_buffer_dirty,
-+ .mergable = ext3_ext_mergable,
-+ .new_block = ext3_new_block_cb,
-+ .remove_extent = ext3_remove_blocks,
-+ .remove_extent_credits = ext3_remove_blocks_credits,
-+};
-+
-+void ext3_init_tree_desc(struct ext3_extents_tree *tree,
-+ struct inode *inode)
-+{
-+ tree->inode = inode;
-+ tree->root = (void *) EXT3_I(inode)->i_data;
-+ tree->buffer = (void *) inode;
-+ tree->buffer_len = sizeof(EXT3_I(inode)->i_data);
-+ tree->cex = (struct ext3_extent *) &EXT3_I(inode)->i_cached_extent;
-+ tree->ops = &ext3_blockmap_helpers;
-+}
-+
-+int ext3_ext_get_block(handle_t *handle, struct inode *inode,
-+ long iblock, struct buffer_head *bh_result, int create)
-+{
-+ struct ext3_ext_path *path = NULL;
-+ struct ext3_extent newex;
-+ struct ext3_extent *ex;
-+ int goal, newblock, err = 0, depth;
-+ struct ext3_extents_tree tree;
-+
-+ clear_bit(BH_New, &bh_result->b_state);
-+ ext3_init_tree_desc(&tree, inode);
-+ ext_debug(&tree, "block %d requested for inode %u\n",
-+ (int) iblock, (unsigned) inode->i_ino);
-+ down_write(&EXT3_I(inode)->truncate_sem);
-+
-+ /* check in cache */
-+ if (ext3_ext_in_cache(&tree, iblock, &newex)) {
-+ if (newex.ee_start == EXT_CACHE_MARK) {
-+ /* this is cached gap */
-+ if (!create) {
-+ /* block isn't allocated yet and
-+ * user don't want to allocate it */
-+ goto out2;
-+ }
-+ /* we should allocate requested block */
-+ } else if (newex.ee_start) {
-+ /* block is already allocated */
-+ newblock = iblock - newex.ee_block + newex.ee_start;
-+ goto out;
-+ }
-+ }
-+
-+ /* find extent for this block */
-+ path = ext3_ext_find_extent(&tree, iblock, NULL);
-+ if (IS_ERR(path)) {
-+ err = PTR_ERR(path);
-+ path = NULL;
-+ goto out2;
-+ }
-+
-+ depth = EXT_DEPTH(&tree);
-+
-+ /*
-+ * consistent leaf must not be empty
-+ * this situations is possible, though, _during_ tree modification
-+ * this is why assert can't be put in ext3_ext_find_extent()
-+ */
-+ EXT_ASSERT(path[depth].p_ext != NULL || depth == 0);
-+
-+ if ((ex = path[depth].p_ext)) {
-+ /* if found exent covers block, simple return it */
-+ if (iblock >= ex->ee_block && iblock < ex->ee_block + ex->ee_len) {
-+ newblock = iblock - ex->ee_block + ex->ee_start;
-+ ext_debug(&tree, "%d fit into %d:%d -> %d\n",
-+ (int) iblock, ex->ee_block, ex->ee_len,
-+ newblock);
-+ ext3_ext_put_in_cache(&tree, ex);
-+ goto out;
-+ }
-+ }
-+
-+ /*
-+ * requested block isn't allocated yet
-+ * we couldn't try to create block if create flag is zero
-+ */
-+ if (!create) {
-+ /* put just found gap into cache to speedup subsequest reqs */
-+ ext3_ext_put_gap_in_cache(&tree, path, iblock);
-+ goto out2;
-+ }
-+
-+ /* allocate new block */
-+ goal = ext3_ext_find_goal(inode, path, iblock);
-+ newblock = ext3_new_block(handle, inode, goal, 0, 0, &err);
-+ if (!newblock)
-+ goto out2;
-+ ext_debug(&tree, "allocate new block: goal %d, found %d\n",
-+ goal, newblock);
-+
-+ /* try to insert new extent into found leaf and return */
-+ newex.ee_block = iblock;
-+ newex.ee_start = newblock;
-+ newex.ee_len = 1;
-+ err = ext3_ext_insert_extent(handle, &tree, path, &newex);
-+ if (err)
-+ goto out2;
-+
-+ if (inode->i_size > EXT3_I(inode)->i_disksize)
-+ EXT3_I(inode)->i_disksize = inode->i_size;
-+
-+ /* previous routine could use block we allocated */
-+ newblock = newex.ee_start;
-+ set_bit(BH_New, &bh_result->b_state);
-+
-+ ext3_ext_put_in_cache(&tree, &newex);
-+out:
-+ ext3_ext_show_leaf(&tree, path);
-+ set_bit(BH_Mapped, &bh_result->b_state);
-+ bh_result->b_dev = inode->i_sb->s_dev;
-+ bh_result->b_blocknr = newblock;
-+out2:
-+ if (path) {
-+ ext3_ext_drop_refs(path);
-+ kfree(path);
-+ }
-+ up_write(&EXT3_I(inode)->truncate_sem);
-+
-+ return err;
-+}
-+
-+void ext3_ext_truncate(struct inode * inode)
-+{
-+ struct address_space *mapping = inode->i_mapping;
-+ struct super_block *sb = inode->i_sb;
-+ struct ext3_extents_tree tree;
-+ unsigned long last_block;
-+ handle_t *handle;
-+ int err = 0;
-+
-+ ext3_init_tree_desc(&tree, inode);
-+
-+ /*
-+ * probably first extent we're gonna free will be last in block
-+ */
-+ err = ext3_writepage_trans_blocks(inode) + 3;
-+ handle = ext3_journal_start(inode, err);
-+ if (IS_ERR(handle))
-+ return;
-+
-+ ext3_block_truncate_page(handle, mapping, inode->i_size);
-+
-+ down_write(&EXT3_I(inode)->truncate_sem);
-+ ext3_ext_invalidate_cache(&tree);
-+
-+ /*
-+ * TODO: optimization is possible here
-+ * probably we need not scaning at all,
-+ * because page truncation is enough
-+ */
-+ if (ext3_orphan_add(handle, inode))
-+ goto out_stop;
-+
-+ /* we have to know where to truncate from in crash case */
-+ EXT3_I(inode)->i_disksize = inode->i_size;
-+ ext3_mark_inode_dirty(handle, inode);
-+
-+ last_block = (inode->i_size + sb->s_blocksize - 1)
-+ >> EXT3_BLOCK_SIZE_BITS(sb);
-+ err = ext3_ext_remove_space(&tree, last_block, EXT_MAX_BLOCK);
-+
-+ /* In a multi-transaction truncate, we only make the final
-+ * transaction synchronous */
-+ if (IS_SYNC(inode))
-+ handle->h_sync = 1;
-+
-+out_stop:
-+ /*
-+ * If this was a simple ftruncate(), and the file will remain alive
-+ * then we need to clear up the orphan record which we created above.
-+ * However, if this was a real unlink then we were called by
-+ * ext3_delete_inode(), and we allow that function to clean up the
-+ * orphan info for us.
-+ */
-+ if (inode->i_nlink)
-+ ext3_orphan_del(handle, inode);
-+
-+ up_write(&EXT3_I(inode)->truncate_sem);
-+ ext3_journal_stop(handle, inode);
-+}
-+
-+/*
-+ * this routine calculate max number of blocks we could modify
-+ * in order to allocate new block for an inode
-+ */
-+int ext3_ext_writepage_trans_blocks(struct inode *inode, int num)
-+{
-+ struct ext3_extents_tree tree;
-+ int needed;
-+
-+ ext3_init_tree_desc(&tree, inode);
-+
-+ needed = ext3_ext_calc_credits_for_insert(&tree, NULL);
-+
-+ /* caller want to allocate num blocks */
-+ needed *= num;
-+
-+#ifdef CONFIG_QUOTA
-+ /*
-+ * FIXME: real calculation should be here
-+ * it depends on blockmap format of qouta file
-+ */
-+ needed += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS;
-+#endif
-+
-+ return needed;
-+}
-+
-+void ext3_extents_initialize_blockmap(handle_t *handle, struct inode *inode)
-+{
-+ struct ext3_extents_tree tree;
-+
-+ ext3_init_tree_desc(&tree, inode);
-+ ext3_extent_tree_init(handle, &tree);
-+}
-+
-+static int
-+ext3_ext_store_extent_cb(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newex, int exist)
-+{
-+ struct ext3_extent_buf *buf = (struct ext3_extent_buf *) tree->private;
-+
-+ if (!exist)
-+ return EXT_CONTINUE;
-+ if (buf->err < 0)
-+ return EXT_BREAK;
-+ if (buf->cur - buf->buffer + sizeof(*newex) > buf->buflen)
-+ return EXT_BREAK;
-+
-+ if (!copy_to_user(buf->cur, newex, sizeof(*newex))) {
-+ buf->err++;
-+ buf->cur += sizeof(*newex);
-+ } else {
-+ buf->err = -EFAULT;
-+ return EXT_BREAK;
-+ }
-+ return EXT_CONTINUE;
-+}
-+
-+static int
-+ext3_ext_collect_stats_cb(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *ex, int exist)
-+{
-+ struct ext3_extent_tree_stats *buf =
-+ (struct ext3_extent_tree_stats *) tree->private;
-+ int depth;
-+
-+ if (!exist)
-+ return EXT_CONTINUE;
-+
-+ depth = EXT_DEPTH(tree);
-+ buf->extents_num++;
-+ if (path[depth].p_ext == EXT_FIRST_EXTENT(path[depth].p_hdr))
-+ buf->leaf_num++;
-+ return EXT_CONTINUE;
-+}
-+
-+int ext3_ext_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ int err = 0;
-+
-+ if (!(EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL))
-+ return -EINVAL;
-+
-+ if (cmd == EXT3_IOC_GET_EXTENTS) {
-+ struct ext3_extent_buf buf;
-+ struct ext3_extents_tree tree;
-+
-+ if (copy_from_user(&buf, (void *) arg, sizeof(buf)))
-+ return -EFAULT;
-+
-+ ext3_init_tree_desc(&tree, inode);
-+ buf.cur = buf.buffer;
-+ buf.err = 0;
-+ tree.private = &buf;
-+ down_write(&EXT3_I(inode)->truncate_sem);
-+ err = ext3_ext_walk_space(&tree, buf.start, EXT_MAX_BLOCK,
-+ ext3_ext_store_extent_cb);
-+ up_write(&EXT3_I(inode)->truncate_sem);
-+ if (err == 0)
-+ err = buf.err;
-+ } else if (cmd == EXT3_IOC_GET_TREE_STATS) {
-+ struct ext3_extent_tree_stats buf;
-+ struct ext3_extents_tree tree;
-+
-+ ext3_init_tree_desc(&tree, inode);
-+ down_write(&EXT3_I(inode)->truncate_sem);
-+ buf.depth = EXT_DEPTH(&tree);
-+ buf.extents_num = 0;
-+ buf.leaf_num = 0;
-+ tree.private = &buf;
-+ err = ext3_ext_walk_space(&tree, 0, EXT_MAX_BLOCK,
-+ ext3_ext_collect_stats_cb);
-+ up_write(&EXT3_I(inode)->truncate_sem);
-+ if (!err)
-+ err = copy_to_user((void *) arg, &buf, sizeof(buf));
-+ } else if (cmd == EXT3_IOC_GET_TREE_DEPTH) {
-+ struct ext3_extents_tree tree;
-+ ext3_init_tree_desc(&tree, inode);
-+ down_write(&EXT3_I(inode)->truncate_sem);
-+ err = EXT_DEPTH(&tree);
-+ up_write(&EXT3_I(inode)->truncate_sem);
-+ }
-+
-+ return err;
-+}
-+
-+EXPORT_SYMBOL(ext3_init_tree_desc);
-+EXPORT_SYMBOL(ext3_mark_inode_dirty);
-+EXPORT_SYMBOL(ext3_ext_invalidate_cache);
-+EXPORT_SYMBOL(ext3_ext_insert_extent);
-+EXPORT_SYMBOL(ext3_ext_walk_space);
-+EXPORT_SYMBOL(ext3_ext_find_goal);
-+EXPORT_SYMBOL(ext3_ext_calc_credits_for_insert);
-+
-Index: linux-2.4.24-b1_4/fs/ext3/ialloc.c
-===================================================================
---- linux-2.4.24-b1_4.orig/fs/ext3/ialloc.c 2004-09-30 14:04:27.000000000 +0800
-+++ linux-2.4.24-b1_4/fs/ext3/ialloc.c 2004-09-30 14:04:33.000000000 +0800
-@@ -592,10 +592,21 @@
- iloc.bh = NULL;
- goto fail;
- }
-- err = ext3_mark_iloc_dirty(handle, inode, &iloc);
-- if (err) goto fail;
-
-+ if (test_opt(sb, EXTENTS)) {
-+ EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL;
-+ ext3_extents_initialize_blockmap(handle, inode);
-+ if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS)) {
-+ err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
-+ if (err) goto fail;
-+ EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS);
-+ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "call ext3_journal_dirty_metadata");
-+ err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
-+ }
-+ }
-
-+ err = ext3_mark_iloc_dirty(handle, inode, &iloc);
-+ if (err) goto fail;
-
- unlock_super (sb);
- if(DQUOT_ALLOC_INODE(inode)) {
-Index: linux-2.4.24-b1_4/fs/ext3/inode.c
-===================================================================
---- linux-2.4.24-b1_4.orig/fs/ext3/inode.c 2004-09-30 14:04:27.000000000 +0800
-+++ linux-2.4.24-b1_4/fs/ext3/inode.c 2004-09-30 14:04:33.000000000 +0800
-@@ -848,6 +848,15 @@
- goto reread;
- }
-
-+static inline int
-+ext3_get_block_wrap(handle_t *handle, struct inode *inode, long block,
-+ struct buffer_head *bh, int create)
-+{
-+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
-+ return ext3_ext_get_block(handle, inode, block, bh, create);
-+ return ext3_get_block_handle(handle, inode, block, bh, create);
-+}
-+
- /*
- * The BKL is not held on entry here.
- */
-@@ -861,7 +870,7 @@
- handle = ext3_journal_current_handle();
- J_ASSERT(handle != 0);
- }
-- ret = ext3_get_block_handle(handle, inode, iblock, bh_result, create);
-+ ret = ext3_get_block_wrap(handle, inode, iblock, bh_result, create);
- return ret;
- }
-
-@@ -879,7 +888,7 @@
- dummy.b_state = 0;
- dummy.b_blocknr = -1000;
- buffer_trace_init(&dummy.b_history);
-- *errp = ext3_get_block_handle(handle, inode, block, &dummy, create);
-+ *errp = ext3_get_block_wrap(handle, inode, block, &dummy, create);
- if (!*errp && buffer_mapped(&dummy)) {
- struct buffer_head *bh;
- bh = sb_getblk(inode->i_sb, dummy.b_blocknr);
-@@ -1403,7 +1412,7 @@
- * This required during truncate. We need to physically zero the tail end
- * of that block so it doesn't yield old data if the file is later grown.
- */
--static int ext3_block_truncate_page(handle_t *handle,
-+int ext3_block_truncate_page(handle_t *handle,
- struct address_space *mapping, loff_t from)
- {
- unsigned long index = from >> PAGE_CACHE_SHIFT;
-@@ -1888,6 +1897,9 @@
-
- ext3_discard_prealloc(inode);
-
-+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
-+ return ext3_ext_truncate(inode);
-+
- handle = start_transaction(inode);
- if (IS_ERR(handle))
- return; /* AKPM: return what? */
-@@ -2536,6 +2548,9 @@
- int indirects = (EXT3_NDIR_BLOCKS % bpp) ? 5 : 3;
- int ret;
-
-+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
-+ return ext3_ext_writepage_trans_blocks(inode, bpp);
-+
- if (ext3_should_journal_data(inode))
- ret = 3 * (bpp + indirects) + 2;
- else
-@@ -2972,7 +2987,7 @@
-
- /* alloc blocks one by one */
- for (i = 0; i < nblocks; i++) {
-- ret = ext3_get_block_handle(handle, inode, blocks[i],
-+ ret = ext3_get_block_wrap(handle, inode, blocks[i],
- &bh_tmp, 1);
- if (ret)
- break;
-@@ -3048,7 +3063,7 @@
- if (blocks[i] != 0)
- continue;
-
-- rc = ext3_get_block_handle(handle, inode, iblock, &bh, 1);
-+ rc = ext3_get_block_wrap(handle, inode, iblock, &bh, 1);
- if (rc) {
- printk(KERN_INFO "ext3_map_inode_page: error %d "
- "allocating block %ld\n", rc, iblock);
-Index: linux-2.4.24-b1_4/fs/ext3/Makefile
-===================================================================
---- linux-2.4.24-b1_4.orig/fs/ext3/Makefile 2004-09-30 14:04:27.000000000 +0800
-+++ linux-2.4.24-b1_4/fs/ext3/Makefile 2004-09-30 14:04:33.000000000 +0800
-@@ -13,7 +13,9 @@
-
- obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
- ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o \
-- xattr_trusted.o
-+ xattr_trusted.o extents.o
-+export-objs += extents.o
-+
- obj-m := $(O_TARGET)
-
- export-objs += xattr.o
-Index: linux-2.4.24-b1_4/fs/ext3/super.c
-===================================================================
---- linux-2.4.24-b1_4.orig/fs/ext3/super.c 2004-09-30 14:04:27.000000000 +0800
-+++ linux-2.4.24-b1_4/fs/ext3/super.c 2004-09-30 14:04:33.000000000 +0800
-@@ -530,6 +530,7 @@
- int i;
-
- J_ASSERT(sbi->s_delete_inodes == 0);
-+ ext3_ext_release(sb);
- ext3_xattr_put_super(sb);
- journal_destroy(sbi->s_journal);
- if (!(sb->s_flags & MS_RDONLY)) {
-@@ -702,6 +703,10 @@
- return 0;
- }
- }
-+ else if (!strcmp (this_char, "extents"))
-+ set_opt (*mount_options, EXTENTS);
-+ else if (!strcmp (this_char, "extdebug"))
-+ set_opt (*mount_options, EXTDEBUG);
- else if (!strcmp (this_char, "grpid") ||
- !strcmp (this_char, "bsdgroups"))
- set_opt (*mount_options, GRPID);
-@@ -1393,6 +1398,8 @@
- test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":
- "writeback");
-
-+ ext3_ext_init(sb);
-+
- return sb;
-
- failed_mount3:
-Index: linux-2.4.24-b1_4/fs/ext3/ioctl.c
-===================================================================
---- linux-2.4.24-b1_4.orig/fs/ext3/ioctl.c 2004-09-30 14:04:22.000000000 +0800
-+++ linux-2.4.24-b1_4/fs/ext3/ioctl.c 2004-09-30 14:04:33.000000000 +0800
-@@ -174,6 +174,10 @@
- return ret;
- }
- #endif
-+ case EXT3_IOC_GET_EXTENTS:
-+ case EXT3_IOC_GET_TREE_STATS:
-+ case EXT3_IOC_GET_TREE_DEPTH:
-+ return ext3_ext_ioctl(inode, filp, cmd, arg);
- default:
- return -ENOTTY;
- }
-Index: linux-2.4.24-b1_4/include/linux/ext3_fs.h
-===================================================================
---- linux-2.4.24-b1_4.orig/include/linux/ext3_fs.h 2004-09-30 14:04:27.000000000 +0800
-+++ linux-2.4.24-b1_4/include/linux/ext3_fs.h 2004-09-30 14:07:09.000000000 +0800
-@@ -184,6 +184,7 @@
- #define EXT3_IMAGIC_FL 0x00002000 /* AFS directory */
- #define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */
- #define EXT3_RESERVED_FL 0x80000000 /* reserved for ext3 lib */
-+#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */
-
- #define EXT3_FL_USER_VISIBLE 0x00005FFF /* User visible flags */
- #define EXT3_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */
-@@ -208,6 +209,9 @@
- #ifdef CONFIG_JBD_DEBUG
- #define EXT3_IOC_WAIT_FOR_READONLY _IOR('f', 99, long)
- #endif
-+#define EXT3_IOC_GET_EXTENTS _IOR('f', 5, long)
-+#define EXT3_IOC_GET_TREE_DEPTH _IOR('f', 6, long)
-+#define EXT3_IOC_GET_TREE_STATS _IOR('f', 7, long)
-
- /*
- * Structure of an inode on the disk
-@@ -327,6 +331,8 @@
- #define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */
- #define EXT3_MOUNT_IOPEN 0x40000 /* Allow access via iopen */
- #define EXT3_MOUNT_IOPEN_NOPRIV 0x80000 /* Make iopen world-readable */
-+#define EXT3_MOUNT_EXTENTS 0x100000 /* Extents support */
-+#define EXT3_MOUNT_EXTDEBUG 0x200000 /* Extents debug */
-
- /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
- #ifndef _LINUX_EXT2_FS_H
-@@ -503,10 +509,12 @@
- #define EXT3_FEATURE_INCOMPAT_FILETYPE 0x0002
- #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
- #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
-+#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
-
- #define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
- #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \
-- EXT3_FEATURE_INCOMPAT_RECOVER)
-+ EXT3_FEATURE_INCOMPAT_RECOVER| \
-+ EXT3_FEATURE_INCOMPAT_EXTENTS)
- #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
- EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
- EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
-@@ -688,6 +696,7 @@
- extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
-
- /* inode.c */
-+extern int ext3_block_truncate_page(handle_t *, struct address_space *, loff_t);
- extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
- extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
- extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
-@@ -769,6 +778,14 @@
- extern struct inode_operations ext3_symlink_inode_operations;
- extern struct inode_operations ext3_fast_symlink_inode_operations;
-
-+/* extents.c */
-+extern int ext3_ext_writepage_trans_blocks(struct inode *, int);
-+extern int ext3_ext_get_block(handle_t *, struct inode *, long,
-+ struct buffer_head *, int);
-+extern void ext3_ext_truncate(struct inode *);
-+extern void ext3_ext_init(struct super_block *);
-+extern void ext3_ext_release(struct super_block *);
-+extern void ext3_extents_initialize_blockmap(handle_t *, struct inode *);
-
- #endif /* __KERNEL__ */
-
-Index: linux-2.4.24-b1_4/include/linux/ext3_extents.h
-===================================================================
---- linux-2.4.24-b1_4.orig/include/linux/ext3_extents.h 2003-01-30 18:24:37.000000000 +0800
-+++ linux-2.4.24-b1_4/include/linux/ext3_extents.h 2004-09-30 14:04:33.000000000 +0800
-@@ -0,0 +1,237 @@
-+/*
-+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
-+ * Written by Alex Tomas <alex@clusterfs.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public Licens
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-
-+ */
-+
-+#ifndef _LINUX_EXT3_EXTENTS
-+#define _LINUX_EXT3_EXTENTS
-+
-+/*
-+ * with AGRESSIVE_TEST defined capacity of index/leaf blocks
-+ * become very little, so index split, in-depth growing and
-+ * other hard changes happens much more often
-+ * this is for debug purposes only
-+ */
-+#define AGRESSIVE_TEST_
-+
-+/*
-+ * if CHECK_BINSEARCH defined, then results of binary search
-+ * will be checked by linear search
-+ */
-+#define CHECK_BINSEARCH_
-+
-+/*
-+ * if EXT_DEBUG is defined you can use 'extdebug' mount option
-+ * to get lots of info what's going on
-+ */
-+#define EXT_DEBUG
-+#ifdef EXT_DEBUG
-+#define ext_debug(tree,fmt,a...) \
-+do { \
-+ if (test_opt((tree)->inode->i_sb, EXTDEBUG)) \
-+ printk(fmt, ##a); \
-+} while (0);
-+#else
-+#define ext_debug(tree,fmt,a...)
-+#endif
-+
-+/*
-+ * if EXT_STATS is defined then stats numbers are collected
-+ * these number will be displayed at umount time
-+ */
-+#define EXT_STATS_
-+
-+
-+#define EXT3_ALLOC_NEEDED 3 /* block bitmap + group desc. + sb */
-+
-+/*
-+ * ext3_inode has i_block array (total 60 bytes)
-+ * first 4 bytes are used to store:
-+ * - tree depth (0 mean there is no tree yet. all extents in the inode)
-+ * - number of alive extents in the inode
-+ */
-+
-+/*
-+ * this is extent on-disk structure
-+ * it's used at the bottom of the tree
-+ */
-+struct ext3_extent {
-+ __u32 ee_block; /* first logical block extent covers */
-+ __u16 ee_len; /* number of blocks covered by extent */
-+ __u16 ee_start_hi; /* high 16 bits of physical block */
-+ __u32 ee_start; /* low 32 bigs of physical block */
-+};
-+
-+/*
-+ * this is index on-disk structure
-+ * it's used at all the levels, but the bottom
-+ */
-+struct ext3_extent_idx {
-+ __u32 ei_block; /* index covers logical blocks from 'block' */
-+ __u32 ei_leaf; /* pointer to the physical block of the next *
-+ * level. leaf or next index could bet here */
-+ __u16 ei_leaf_hi; /* high 16 bits of physical block */
-+ __u16 ei_unused;
-+};
-+
-+/*
-+ * each block (leaves and indexes), even inode-stored has header
-+ */
-+struct ext3_extent_header {
-+ __u16 eh_magic; /* probably will support different formats */
-+ __u16 eh_entries; /* number of valid entries */
-+ __u16 eh_max; /* capacity of store in entries */
-+ __u16 eh_depth; /* has tree real underlaying blocks? */
-+ __u32 eh_generation; /* generation of the tree */
-+};
-+
-+#define EXT3_EXT_MAGIC 0xf30a
-+
-+/*
-+ * array of ext3_ext_path contains path to some extent
-+ * creation/lookup routines use it for traversal/splitting/etc
-+ * truncate uses it to simulate recursive walking
-+ */
-+struct ext3_ext_path {
-+ __u32 p_block;
-+ __u16 p_depth;
-+ struct ext3_extent *p_ext;
-+ struct ext3_extent_idx *p_idx;
-+ struct ext3_extent_header *p_hdr;
-+ struct buffer_head *p_bh;
-+};
-+
-+/*
-+ * structure for external API
-+ */
-+
-+/*
-+ * ext3_extents_tree is used to pass initial information
-+ * to top-level extents API
-+ */
-+struct ext3_extents_helpers;
-+struct ext3_extents_tree {
-+ struct inode *inode; /* inode which tree belongs to */
-+ void *root; /* ptr to data top of tree resides at */
-+ void *buffer; /* will be passed as arg to ^^ routines */
-+ int buffer_len;
-+ void *private;
-+ struct ext3_extent *cex;/* last found extent */
-+ struct ext3_extents_helpers *ops;
-+};
-+
-+struct ext3_extents_helpers {
-+ int (*get_write_access)(handle_t *h, void *buffer);
-+ int (*mark_buffer_dirty)(handle_t *h, void *buffer);
-+ int (*mergable)(struct ext3_extent *ex1, struct ext3_extent *ex2);
-+ int (*remove_extent_credits)(struct ext3_extents_tree *,
-+ struct ext3_extent *, unsigned long,
-+ unsigned long);
-+ int (*remove_extent)(struct ext3_extents_tree *,
-+ struct ext3_extent *, unsigned long,
-+ unsigned long);
-+ int (*new_block)(handle_t *, struct ext3_extents_tree *,
-+ struct ext3_ext_path *, struct ext3_extent *,
-+ int *);
-+};
-+
-+/*
-+ * to be called by ext3_ext_walk_space()
-+ * negative retcode - error
-+ * positive retcode - signal for ext3_ext_walk_space(), see below
-+ * callback must return valid extent (passed or newly created)
-+ */
-+typedef int (*ext_prepare_callback)(struct ext3_extents_tree *,
-+ struct ext3_ext_path *,
-+ struct ext3_extent *, int);
-+
-+#define EXT_CONTINUE 0
-+#define EXT_BREAK 1
-+#define EXT_REPEAT 2
-+
-+
-+#define EXT_MAX_BLOCK 0xffffffff
-+#define EXT_CACHE_MARK 0xffff
-+
-+
-+#define EXT_FIRST_EXTENT(__hdr__) \
-+ ((struct ext3_extent *) (((char *) (__hdr__)) + \
-+ sizeof(struct ext3_extent_header)))
-+#define EXT_FIRST_INDEX(__hdr__) \
-+ ((struct ext3_extent_idx *) (((char *) (__hdr__)) + \
-+ sizeof(struct ext3_extent_header)))
-+#define EXT_HAS_FREE_INDEX(__path__) \
-+ ((__path__)->p_hdr->eh_entries < (__path__)->p_hdr->eh_max)
-+#define EXT_LAST_EXTENT(__hdr__) \
-+ (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_entries - 1)
-+#define EXT_LAST_INDEX(__hdr__) \
-+ (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_entries - 1)
-+#define EXT_MAX_EXTENT(__hdr__) \
-+ (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1)
-+#define EXT_MAX_INDEX(__hdr__) \
-+ (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1)
-+
-+#define EXT_ROOT_HDR(tree) \
-+ ((struct ext3_extent_header *) (tree)->root)
-+#define EXT_BLOCK_HDR(bh) \
-+ ((struct ext3_extent_header *) (bh)->b_data)
-+#define EXT_DEPTH(_t_) \
-+ (((struct ext3_extent_header *)((_t_)->root))->eh_depth)
-+#define EXT_GENERATION(_t_) \
-+ (((struct ext3_extent_header *)((_t_)->root))->eh_generation)
-+
-+
-+#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
-+
-+
-+/*
-+ * this structure is used to gather extents from the tree via ioctl
-+ */
-+struct ext3_extent_buf {
-+ unsigned long start;
-+ int buflen;
-+ void *buffer;
-+ void *cur;
-+ int err;
-+};
-+
-+/*
-+ * this structure is used to collect stats info about the tree
-+ */
-+struct ext3_extent_tree_stats {
-+ int depth;
-+ int extents_num;
-+ int leaf_num;
-+};
-+
-+void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *);
-+extern int ext3_extent_tree_init(handle_t *, struct ext3_extents_tree *);
-+extern int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *, struct ext3_ext_path *);
-+extern int ext3_ext_insert_extent(handle_t *, struct ext3_extents_tree *, struct ext3_ext_path *, struct ext3_extent *);
-+extern int ext3_ext_walk_space(struct ext3_extents_tree *, unsigned long, unsigned long, ext_prepare_callback);
-+extern int ext3_ext_remove_space(struct ext3_extents_tree *, unsigned long, unsigned long);
-+extern struct ext3_ext_path * ext3_ext_find_extent(struct ext3_extents_tree *, int, struct ext3_ext_path *);
-+
-+static inline void
-+ext3_ext_invalidate_cache(struct ext3_extents_tree *tree)
-+{
-+ if (tree->cex)
-+ tree->cex->ee_len = 0;
-+}
-+
-+
-+#endif /* _LINUX_EXT3_EXTENTS */
-+
-Index: linux-2.4.24-b1_4/include/linux/ext3_fs_i.h
-===================================================================
---- linux-2.4.24-b1_4.orig/include/linux/ext3_fs_i.h 2004-09-30 14:04:27.000000000 +0800
-+++ linux-2.4.24-b1_4/include/linux/ext3_fs_i.h 2004-09-30 14:04:33.000000000 +0800
-@@ -76,6 +76,8 @@
- * by other means, so we have truncate_sem.
- */
- struct rw_semaphore truncate_sem;
-+
-+ __u32 i_cached_extent[3];
- };
-
- #endif /* _LINUX_EXT3_FS_I */
+++ /dev/null
-Index: linux-2.4.24/fs/ext3/inode.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/inode.c 2004-05-18 12:34:48.000000000 -0700
-+++ linux-2.4.24/fs/ext3/inode.c 2004-05-18 12:47:50.000000000 -0700
-@@ -2244,6 +2244,12 @@
- else
- inode->u.ext3_i.i_extra_isize = 0;
-
-+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) {
-+ inode->u.ext3_i.i_cached_extent[0] = 0;
-+ inode->u.ext3_i.i_cached_extent[1] = 0;
-+ inode->u.ext3_i.i_cached_extent[2] = 0;
-+ }
-+
- if (S_ISREG(inode->i_mode)) {
- inode->i_op = &ext3_file_inode_operations;
- inode->i_fop = &ext3_file_operations;
-@@ -2659,6 +2665,10 @@
-
- memcpy(nei->i_data, oei->i_data, sizeof(nei->i_data));
- memset(oei->i_data, 0, sizeof(oei->i_data));
-+ if (EXT3_I(old_inode)->i_flags & EXT3_EXTENTS_FL) {
-+ EXT3_I(new_inode)->i_flags |= EXT3_EXTENTS_FL;
-+ ext3_extents_initialize_blockmap(handle, old_inode);
-+ }
-
- nei->i_disksize = oei->i_disksize;
- nei->i_state |= EXT3_STATE_DELETE;
+++ /dev/null
-Index: linux-2.4.24/fs/ext3/extents-in-ea.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/extents-in-ea.c 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.24/fs/ext3/extents-in-ea.c 2004-08-10 16:13:06.000000000 +0400
-@@ -0,0 +1,224 @@
-+/*
-+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com
-+ * Written by Alex Tomas <alex@clusterfs.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public Licens
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/fs.h>
-+#include <linux/time.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/jbd.h>
-+#include <linux/smp_lock.h>
-+#include <linux/highuid.h>
-+#include <linux/pagemap.h>
-+#include <linux/quotaops.h>
-+#include <linux/string.h>
-+#include <linux/ext3_extents.h>
-+#include <linux/ext3_xattr.h>
-+#include <linux/slab.h>
-+#include <asm/uaccess.h>
-+
-+static int ext3_get_ea_write_access(handle_t *handle, void *buffer)
-+{
-+ struct buffer_head *bh = (struct buffer_head *) buffer;
-+ return ext3_journal_get_write_access(handle, bh);
-+}
-+
-+static int ext3_mark_ea_buffer_dirty(handle_t *handle, void *buffer)
-+{
-+ struct buffer_head *bh = (struct buffer_head *) buffer;
-+ ext3_journal_dirty_metadata(handle, bh);
-+ return 0;
-+}
-+
-+static struct ext3_extents_helpers ext3_ea_helpers = {
-+ .get_write_access = ext3_get_ea_write_access,
-+ .mark_buffer_dirty = ext3_mark_ea_buffer_dirty,
-+ .mergable = NULL,
-+ .new_block = NULL,
-+ .remove_extent = NULL,
-+ .remove_extent_credits = NULL,
-+};
-+
-+int ext3_init_tree_in_ea_desc(struct ext3_extents_tree *tree,
-+ struct inode *inode, int name_index,
-+ const char *eaname)
-+{
-+ struct buffer_head *bh;
-+ int offset, err, size;
-+
-+ err = ext3_xattr_get_ea_loc(inode, name_index, eaname,
-+ &bh, &offset, &size);
-+ if (err)
-+ return err;
-+
-+ EXT_ASSERT(bh);
-+ EXT_ASSERT(size >= sizeof(struct ext3_extent_header)
-+ + sizeof(struct ext3_extent));
-+ tree->inode = inode;
-+ tree->root = (void *) bh->b_data + offset;
-+ tree->buffer_len = size;
-+ tree->buffer = (void *) bh;
-+ tree->ops = &ext3_ea_helpers;
-+ tree->cex = NULL; /* FIXME: add cache store later */
-+ return 0;
-+}
-+
-+void ext3_release_tree_in_ea_desc(struct ext3_extents_tree *tree)
-+{
-+ struct buffer_head *bh;
-+
-+ bh = (struct buffer_head *) tree->buffer;
-+ EXT_ASSERT(bh);
-+ brelse(bh);
-+}
-+
-+int ext3_init_tree_in_ea(struct inode *inode, int name_index,
-+ const char *eaname, int size)
-+{
-+ struct ext3_extents_tree tree;
-+ handle_t *handle;
-+ char *root;
-+ int err;
-+
-+ root = kmalloc(size, GFP_USER);
-+ if (!root)
-+ return -ENOMEM;
-+ memset(root, 0, size);
-+
-+ /* first, create ea to store root of the tree */
-+ handle = ext3_journal_start(inode, EXT3_ALLOC_NEEDED + 3);
-+ if (IS_ERR(handle))
-+ return PTR_ERR(handle);
-+ if ((err = ext3_xattr_set(handle, inode, name_index,
-+ eaname, root, size, 0)))
-+ goto out;
-+ if ((err = ext3_init_tree_in_ea_desc(&tree, inode, name_index, eaname)))
-+ goto out;
-+ err = ext3_extent_tree_init(handle, &tree);
-+ ext3_release_tree_in_ea_desc(&tree);
-+out:
-+ ext3_journal_stop(handle, inode);
-+ kfree(root);
-+ return err;
-+}
-+
-+static int
-+ext3_ext_in_ea_new_extent(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newex, int exist)
-+{
-+ struct inode *inode = tree->inode;
-+ handle_t *handle;
-+ int needed, err;
-+ unsigned long tgen;
-+
-+ if (exist)
-+ return EXT_CONTINUE;
-+
-+ tgen = EXT_GENERATION(tree);
-+ needed = ext3_ext_calc_credits_for_insert(tree, path);
-+ up_write(&EXT3_I(inode)->truncate_sem);
-+ handle = ext3_journal_start(tree->inode, needed + 10);
-+ if (IS_ERR(handle)) {
-+ down_write(&EXT3_I(inode)->truncate_sem);
-+ return PTR_ERR(handle);
-+ }
-+
-+ if (tgen != EXT_GENERATION(tree)) {
-+ /* the tree has changed. so path can be invalid at moment */
-+ ext3_journal_stop(handle, inode);
-+ down_write(&EXT3_I(inode)->truncate_sem);
-+ return EXT_REPEAT;
-+ }
-+
-+ down_write(&EXT3_I(inode)->truncate_sem);
-+
-+ /* insert new extent */
-+ newex->ee_start = 0;
-+ err = ext3_ext_insert_extent(handle, tree, path, newex);
-+ if (!err)
-+ ext3_journal_stop(handle, tree->inode);
-+
-+ return err;
-+}
-+
-+int ext3_ext_in_ea_alloc_space(struct inode *inode, int name_index,
-+ const char *eaname, unsigned long from,
-+ unsigned long num)
-+{
-+ struct ext3_extents_tree tree;
-+ int err;
-+
-+ err = ext3_init_tree_in_ea_desc(&tree, inode, name_index, eaname);
-+ if (err == 0) {
-+ down_write(&EXT3_I(inode)->truncate_sem);
-+ err = ext3_ext_walk_space(&tree, from, num,
-+ ext3_ext_in_ea_new_extent);
-+ ext3_release_tree_in_ea_desc(&tree);
-+ up_write(&EXT3_I(inode)->truncate_sem);
-+ }
-+ return err;
-+}
-+
-+int ext3_ext_in_ea_remove_space(struct inode *inode, int name_index,
-+ const char *eaname, unsigned long from,
-+ unsigned long num)
-+{
-+ struct ext3_extents_tree tree;
-+ int err;
-+
-+ err = ext3_init_tree_in_ea_desc(&tree, inode, name_index, eaname);
-+ if (err == 0) {
-+ err = ext3_ext_remove_space(&tree, from, num);
-+ ext3_release_tree_in_ea_desc(&tree);
-+ }
-+ return err;
-+}
-+
-+int ext3_ext_in_ea_presence(struct inode *inode, int name_index,
-+ const char *eaname, unsigned long block)
-+{
-+ struct ext3_extents_tree tree;
-+ struct ext3_ext_path *path;
-+ struct ext3_extent *ex;
-+ int err, depth;
-+
-+ err = ext3_init_tree_in_ea_desc(&tree, inode, name_index, eaname);
-+ if (err)
-+ return err;
-+
-+ /* find extent for this block */
-+ path = ext3_ext_find_extent(&tree, block, NULL);
-+ if (IS_ERR(path)) {
-+ err = PTR_ERR(path);
-+ goto out;
-+ }
-+
-+ depth = EXT_DEPTH(&tree);
-+ ex = path[depth].p_ext;
-+ if (!ex) {
-+ /* there is no extent yet */
-+ goto out;
-+ }
-+
-+ if (block >= ex->ee_block && block < ex->ee_block + ex->ee_len)
-+ err = 1;
-+out:
-+ ext3_release_tree_in_ea_desc(&tree);
-+ return err;
-+}
-+
-Index: linux-2.4.24/fs/ext3/Makefile
-===================================================================
---- linux-2.4.24.orig/fs/ext3/Makefile 2004-08-10 16:09:22.000000000 +0400
-+++ linux-2.4.24/fs/ext3/Makefile 2004-08-10 16:10:10.000000000 +0400
-@@ -19,7 +19,7 @@
- obj-m := $(O_TARGET)
-
- export-objs += xattr.o
--obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o
-+obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o extents-in-ea.o
- obj-$(CONFIG_EXT3_FS_XATTR_USER) += xattr_user.o
-
- include $(TOPDIR)/Rules.make
-Index: linux-2.4.24/fs/ext3/xattr.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/xattr.c 2004-08-07 16:35:25.000000000 +0400
-+++ linux-2.4.24/fs/ext3/xattr.c 2004-08-10 16:10:10.000000000 +0400
-@@ -771,7 +771,8 @@
- */
- int
- ext3_xattr_ibody_find(struct inode *inode, int name_index,
-- const char *name, struct ext3_xattr_entry *rentry, int *free)
-+ const char *name, struct ext3_xattr_entry *rentry, int *free,
-+ struct buffer_head **bh, int *offset)
- {
- struct ext3_xattr_entry *last;
- struct ext3_inode *raw_inode;
-@@ -818,6 +819,15 @@
- name_len == last->e_name_len &&
- !memcmp(name, last->e_name, name_len)) {
- memcpy(rentry, last, sizeof(struct ext3_xattr_entry));
-+ if (offset) {
-+ void *voff;
-+ voff = start + le16_to_cpu(last->e_value_offs);
-+ *offset = voff - (void *) iloc.bh->b_data;
-+ }
-+ if (bh) {
-+ get_bh(iloc.bh);
-+ *bh = iloc.bh;
-+ }
- ret = 0;
- } else {
- *free -= EXT3_XATTR_LEN(last->e_name_len);
-@@ -838,7 +848,8 @@
- */
- int
- ext3_xattr_block_find(struct inode *inode, int name_index, const char *name,
-- struct ext3_xattr_entry *rentry, int *free)
-+ struct ext3_xattr_entry *rentry, int *free,
-+ struct buffer_head **tbh, int *offset)
- {
- struct buffer_head *bh = NULL;
- struct ext3_xattr_entry *entry;
-@@ -881,6 +892,12 @@
- memcmp(name, entry->e_name, name_len) == 0) {
- memcpy(rentry, entry, sizeof(struct ext3_xattr_entry));
- error = 0;
-+ if (offset)
-+ *offset = le16_to_cpu(entry->e_value_offs);
-+ if (tbh) {
-+ get_bh(bh);
-+ *tbh = bh;
-+ }
- } else {
- *free -= EXT3_XATTR_LEN(entry->e_name_len);
- *free -= le32_to_cpu(entry->e_value_size);
-@@ -1073,7 +1090,8 @@
- return -ERANGE;
-
- /* try to find attribute in inode body */
-- err = ext3_xattr_ibody_find(inode, name_index, name, &entry, &free1);
-+ err = ext3_xattr_ibody_find(inode, name_index, name,
-+ &entry, &free1, NULL, NULL);
- if (err == 0) {
- /* found EA in inode */
- found = 1;
-@@ -1082,7 +1100,7 @@
- /* there is no such attribute in inode body */
- /* try to find attribute in dedicated block */
- err = ext3_xattr_block_find(inode, name_index, name,
-- &entry, &free2);
-+ &entry, &free2, NULL, NULL);
- if (err != 0 && err != -ENOENT) {
- /* not found EA in block */
- goto finish;
-@@ -1138,6 +1156,38 @@
- return err;
- }
-
-+int ext3_xattr_get_ea_loc(struct inode *inode, int name_index,
-+ const char *name, struct buffer_head **bh,
-+ int *offset, int *size)
-+{
-+ int free1 = -1, free2 = -1, err, name_len;
-+ struct ext3_xattr_entry entry;
-+
-+ ea_idebug(inode, "name=%d.%s", name_index, name);
-+
-+ if (name == NULL)
-+ return -EINVAL;
-+ name_len = strlen(name);
-+ if (name_len > 255)
-+ return -ERANGE;
-+
-+ down(&ext3_xattr_sem);
-+
-+ /* try to find attribute in inode body */
-+ err = ext3_xattr_ibody_find(inode, name_index, name,
-+ &entry, &free1, bh, offset);
-+ if (err == -ENOENT) {
-+ /* there is no such attribute in inode body */
-+ /* try to find attribute in dedicated block */
-+ err = ext3_xattr_block_find(inode, name_index, name,
-+ &entry, &free2, bh, offset);
-+ }
-+ if (err == 0 && size)
-+ *size = le32_to_cpu(entry.e_value_size);
-+ up(&ext3_xattr_sem);
-+ return err;
-+}
-+
- /*
- * ext3_xattr_block_set()
- *
-Index: linux-2.4.24/include/linux/ext3_xattr.h
-===================================================================
---- linux-2.4.24.orig/include/linux/ext3_xattr.h 2004-08-07 16:35:25.000000000 +0400
-+++ linux-2.4.24/include/linux/ext3_xattr.h 2004-08-10 16:10:10.000000000 +0400
-@@ -80,6 +80,7 @@
- extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
- extern int ext3_xattr_list(struct inode *, char *, size_t);
- extern int ext3_xattr_set(handle_t *handle, struct inode *, int, const char *, const void *, size_t, int);
-+extern int ext3_xattr_get_ea_loc(struct inode *, int, const char *, struct buffer_head **, int *, int *);
-
- extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
- extern void ext3_xattr_put_super(struct super_block *);
+++ /dev/null
-Index: linux-2.4.24/fs/ext3/extents-in-ea.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/extents-in-ea.c 2004-08-10 16:18:18.000000000 +0400
-+++ linux-2.4.24/fs/ext3/extents-in-ea.c 2004-08-10 16:19:13.000000000 +0400
-@@ -115,7 +115,7 @@
- kfree(root);
- return err;
- }
--
-+EXPORT_SYMBOL(ext3_init_tree_in_ea);
- static int
- ext3_ext_in_ea_new_extent(struct ext3_extents_tree *tree,
- struct ext3_ext_path *path,
-@@ -173,7 +173,7 @@
- }
- return err;
- }
--
-+EXPORT_SYMBOL(ext3_ext_in_ea_alloc_space);
- int ext3_ext_in_ea_remove_space(struct inode *inode, int name_index,
- const char *eaname, unsigned long from,
- unsigned long num)
-@@ -188,7 +188,7 @@
- }
- return err;
- }
--
-+EXPORT_SYMBOL(ext3_ext_in_ea_remove_space);
- int ext3_ext_in_ea_presence(struct inode *inode, int name_index,
- const char *eaname, unsigned long block)
- {
-@@ -331,3 +331,49 @@
- return err;
- }
-
-+EXPORT_SYMBOL(ext3_ext_in_ea_ioctl);
-+int ext3_ext_in_ea_get_extents(struct inode *inode, int name_index,
-+ const char *eaname, char **buf, int *size)
-+{
-+ /*allocate the buffer and put the extents there*/
-+ struct ext3_extents_tree tree;
-+ struct ext3_extent_buf ex_buf;
-+ int err;
-+ err = ext3_init_tree_in_ea_desc(&tree, inode, name_index, eaname);
-+ if (err)
-+ goto out;
-+ ex_buf.cur = *buf;
-+ ex_buf.err = 0;
-+ tree.private = &ex_buf;
-+ ex_buf.start = 0;
-+
-+ err = ext3_ext_walk_space(&tree, ex_buf.start, EXT_MAX_BLOCK,
-+ ext3_ext_store_extent_cb);
-+ if (err == 0)
-+ err = ex_buf.err;
-+ ext3_release_tree_in_ea_desc(&tree);
-+out:
-+ return err;
-+}
-+EXPORT_SYMBOL(ext3_ext_in_ea_get_extents);
-+int ext3_ext_in_ea_get_extents_num(struct inode *inode, int name_index,
-+ const char *eaname, int *size)
-+{
-+ struct ext3_extents_tree tree;
-+ struct ext3_extent_tree_stats stats_buf;
-+ int err = 0, ext_num;
-+ /*get extents number*/
-+ err = ext3_init_tree_in_ea_desc(&tree, inode, name_index, eaname);
-+ if (err)
-+ return err;
-+ tree.private = &stats_buf;
-+ err = ext3_ext_walk_space(&tree, 0, EXT_MAX_BLOCK,
-+ ext3_ext_collect_stats_cb);
-+ ext_num = stats_buf.extents_num;
-+ ext3_release_tree_in_ea_desc(&tree);
-+
-+ *size = ext_num * sizeof(struct ext3_extent);
-+
-+ return err;
-+}
-+EXPORT_SYMBOL(ext3_ext_in_ea_get_extents_num);
-Index: linux-2.4.24/fs/ext3/Makefile
-===================================================================
---- linux-2.4.24.orig/fs/ext3/Makefile 2004-08-10 16:10:10.000000000 +0400
-+++ linux-2.4.24/fs/ext3/Makefile 2004-08-10 16:18:47.000000000 +0400
-@@ -13,13 +13,16 @@
-
- obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
- ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o \
-- xattr_trusted.o extents.o
-+ xattr_trusted.o extents.o extents-in-ea.o
- export-objs += extents.o
-
- obj-m := $(O_TARGET)
-
- export-objs += xattr.o
--obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o extents-in-ea.o
-+ifeq ($(CONFIG_EXT3_FS_XATTR),y)
-+export-objs += extents-in-ea.o
-+endif
-+obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o
- obj-$(CONFIG_EXT3_FS_XATTR_USER) += xattr_user.o
-
- include $(TOPDIR)/Rules.make
-Index: linux-2.4.24/fs/ext3/ioctl.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/ioctl.c 2004-08-10 16:14:40.000000000 +0400
-+++ linux-2.4.24/fs/ext3/ioctl.c 2004-08-10 16:18:47.000000000 +0400
-@@ -11,6 +11,7 @@
- #include <linux/jbd.h>
- #include <linux/ext3_fs.h>
- #include <linux/ext3_jbd.h>
-+#include <linux/ext3_extents.h>
- #include <linux/sched.h>
- #include <asm/uaccess.h>
-
+++ /dev/null
-Index: linux-2.4.24/fs/ext3/extents-in-ea.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/extents-in-ea.c 2004-08-10 16:13:06.000000000 +0400
-+++ linux-2.4.24/fs/ext3/extents-in-ea.c 2004-08-10 16:18:18.000000000 +0400
-@@ -222,3 +222,112 @@
- return err;
- }
-
-+static int
-+ext3_ext_store_extent_cb(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *newex, int exist)
-+{
-+ struct ext3_extent_buf *buf = (struct ext3_extent_buf *) tree->private;
-+
-+ if (!exist)
-+ return EXT_CONTINUE;
-+ if (buf->err < 0)
-+ return EXT_BREAK;
-+ if (buf->cur - buf->buffer + sizeof(*newex) > buf->buflen)
-+ return EXT_BREAK;
-+
-+ if (!copy_to_user(buf->cur, newex, sizeof(*newex))) {
-+ buf->err++;
-+ buf->cur += sizeof(*newex);
-+ } else {
-+ buf->err = -EFAULT;
-+ return EXT_BREAK;
-+ }
-+ return EXT_CONTINUE;
-+}
-+
-+static int
-+ext3_ext_collect_stats_cb(struct ext3_extents_tree *tree,
-+ struct ext3_ext_path *path,
-+ struct ext3_extent *ex, int exist)
-+{
-+ struct ext3_extent_tree_stats *buf =
-+ (struct ext3_extent_tree_stats *) tree->private;
-+ int depth;
-+
-+ if (!exist)
-+ return EXT_CONTINUE;
-+
-+ depth = EXT_DEPTH(tree);
-+ buf->extents_num++;
-+ if (path[depth].p_ext == EXT_FIRST_EXTENT(path[depth].p_hdr))
-+ buf->leaf_num++;
-+ return EXT_CONTINUE;
-+}
-+
-+struct ea_tree_desc {
-+ int name_index;
-+ char eaname[256];
-+};
-+
-+int ext3_ext_in_ea_ioctl(struct inode *inode, struct file *filp,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ int err = 0;
-+
-+ if (cmd == EXT3_IOC_EA_TREE_INIT) {
-+ struct ea_tree_desc desc;
-+
-+ if (copy_from_user(&desc, (void *) arg, sizeof(desc)))
-+ return -EFAULT;
-+ err = ext3_init_tree_in_ea(inode, desc.name_index,
-+ desc.eaname, 64);
-+ } else if (cmd == EXT3_IOC_GET_EA_EXTENTS) {
-+ struct ext3_extents_tree tree;
-+ struct ext3_extent_buf buf;
-+ struct ea_tree_desc desc;
-+
-+ if (copy_from_user(&buf, (void *) arg, sizeof(buf)))
-+ return -EFAULT;
-+ if (copy_from_user(&desc, buf.cur, sizeof(desc)))
-+ return -EFAULT;
-+ err = ext3_init_tree_in_ea_desc(&tree, inode,
-+ desc.name_index, desc.eaname);
-+ if (err)
-+ goto out;
-+ buf.cur = buf.buffer;
-+ buf.err = 0;
-+ tree.private = &buf;
-+ err = ext3_ext_walk_space(&tree, buf.start, EXT_MAX_BLOCK,
-+ ext3_ext_store_extent_cb);
-+ if (err == 0)
-+ err = buf.err;
-+ ext3_release_tree_in_ea_desc(&tree);
-+ } else if (cmd == EXT3_IOC_EA_TREE_ALLOCATE) {
-+ struct ext3_extent_buf buf;
-+ struct ea_tree_desc desc;
-+
-+ if (copy_from_user(&buf, (void *) arg, sizeof(buf)))
-+ return -EFAULT;
-+ if (copy_from_user(&desc, buf.cur, sizeof(desc)))
-+ return -EFAULT;
-+ err = ext3_ext_in_ea_alloc_space(inode, desc.name_index,
-+ desc.eaname, buf.start,
-+ buf.err);
-+ } else if (cmd == EXT3_IOC_EA_TREE_REMOVE) {
-+ struct ext3_extent_buf buf;
-+ struct ea_tree_desc desc;
-+
-+ if (copy_from_user(&buf, (void *) arg, sizeof(buf)))
-+ return -EFAULT;
-+ if (copy_from_user(&desc, buf.cur, sizeof(desc)))
-+ return -EFAULT;
-+ err = ext3_ext_in_ea_remove_space(inode, desc.name_index,
-+ desc.eaname, buf.start,
-+ buf.err);
-+ }
-+
-+out:
-+ return err;
-+}
-+
-Index: linux-2.4.24/fs/ext3/ioctl.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/ioctl.c 2004-08-10 16:09:22.000000000 +0400
-+++ linux-2.4.24/fs/ext3/ioctl.c 2004-08-10 16:14:40.000000000 +0400
-@@ -178,6 +178,13 @@
- case EXT3_IOC_GET_TREE_STATS:
- case EXT3_IOC_GET_TREE_DEPTH:
- return ext3_ext_ioctl(inode, filp, cmd, arg);
-+ case EXT3_IOC_GET_EA_EXTENTS:
-+ case EXT3_IOC_GET_EA_TREE_DEPTH:
-+ case EXT3_IOC_GET_EA_TREE_STATS:
-+ case EXT3_IOC_EA_TREE_INIT:
-+ case EXT3_IOC_EA_TREE_ALLOCATE:
-+ case EXT3_IOC_EA_TREE_REMOVE:
-+ return ext3_ext_in_ea_ioctl(inode, filp, cmd, arg);
- default:
- return -ENOTTY;
- }
-Index: linux-2.4.24/include/linux/ext3_fs.h
-===================================================================
---- linux-2.4.24.orig/include/linux/ext3_fs.h 2004-08-10 16:09:22.000000000 +0400
-+++ linux-2.4.24/include/linux/ext3_fs.h 2004-08-10 16:14:40.000000000 +0400
-@@ -214,6 +214,14 @@
- #define EXT3_IOC_GET_TREE_DEPTH _IOR('f', 6, long)
- #define EXT3_IOC_GET_TREE_STATS _IOR('f', 7, long)
-
-+#define EXT3_IOC_GET_EA_EXTENTS _IOR('f', 10, long)
-+#define EXT3_IOC_GET_EA_TREE_DEPTH _IOR('f', 11, long)
-+#define EXT3_IOC_GET_EA_TREE_STATS _IOR('f', 12, long)
-+#define EXT3_IOC_EA_TREE_INIT _IOW('f', 13, long)
-+#define EXT3_IOC_EA_TREE_ALLOCATE _IOW('f', 14, long)
-+#define EXT3_IOC_EA_TREE_REMOVE _IOW('f', 15, long)
-+
-+
- /*
- * Structure of an inode on the disk
- */
+++ /dev/null
- fs/ext3/Makefile | 2
- fs/ext3/dir.c | 302 +++++++++
- fs/ext3/file.c | 3
- fs/ext3/hash.c | 215 ++++++
- fs/ext3/namei.c | 1421 ++++++++++++++++++++++++++++++++++++++++-----
- fs/ext3/super.c | 7
- include/linux/ext3_fs.h | 85 ++
- include/linux/ext3_fs_sb.h | 2
- include/linux/ext3_jbd.h | 2
- include/linux/rbtree.h | 2
- lib/rbtree.c | 42 +
- 11 files changed, 1922 insertions(+), 161 deletions(-)
-
---- linux-2.4.22-ac1/fs/ext3/dir.c~ext3-htree-2.4.22-rh 2001-11-10 01:25:04.000000000 +0300
-+++ linux-2.4.22-ac1-alexey/fs/ext3/dir.c 2003-09-25 14:58:30.000000000 +0400
-@@ -21,12 +21,16 @@
- #include <linux/fs.h>
- #include <linux/jbd.h>
- #include <linux/ext3_fs.h>
-+#include <linux/slab.h>
-+#include <linux/rbtree.h>
-
- static unsigned char ext3_filetype_table[] = {
- DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
- };
-
- static int ext3_readdir(struct file *, void *, filldir_t);
-+static int ext3_dx_readdir(struct file * filp,
-+ void * dirent, filldir_t filldir);
-
- struct file_operations ext3_dir_operations = {
- read: generic_read_dir,
-@@ -35,6 +39,17 @@ struct file_operations ext3_dir_operatio
- fsync: ext3_sync_file, /* BKL held */
- };
-
-+
-+static unsigned char get_dtype(struct super_block *sb, int filetype)
-+{
-+ if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_FILETYPE) ||
-+ (filetype >= EXT3_FT_MAX))
-+ return DT_UNKNOWN;
-+
-+ return (ext3_filetype_table[filetype]);
-+}
-+
-+
- int ext3_check_dir_entry (const char * function, struct inode * dir,
- struct ext3_dir_entry_2 * de,
- struct buffer_head * bh,
-@@ -79,6 +94,16 @@ static int ext3_readdir(struct file * fi
-
- sb = inode->i_sb;
-
-+ if (is_dx(inode)) {
-+ err = ext3_dx_readdir(filp, dirent, filldir);
-+ if (err != ERR_BAD_DX_DIR)
-+ return err;
-+ /*
-+ * We don't set the inode dirty flag since it's not
-+ * critical that it get flushed back to the disk.
-+ */
-+ EXT3_I(filp->f_dentry->d_inode)->i_flags &= ~EXT3_INDEX_FL;
-+ }
- stored = 0;
- bh = NULL;
- offset = filp->f_pos & (sb->s_blocksize - 1);
-@@ -162,18 +187,12 @@ revalidate:
- * during the copy operation.
- */
- unsigned long version = filp->f_version;
-- unsigned char d_type = DT_UNKNOWN;
-
-- if (EXT3_HAS_INCOMPAT_FEATURE(sb,
-- EXT3_FEATURE_INCOMPAT_FILETYPE)
-- && de->file_type < EXT3_FT_MAX)
-- d_type =
-- ext3_filetype_table[de->file_type];
- error = filldir(dirent, de->name,
- de->name_len,
- filp->f_pos,
- le32_to_cpu(de->inode),
-- d_type);
-+ get_dtype(sb, de->file_type));
- if (error)
- break;
- if (version != filp->f_version)
-@@ -188,3 +207,272 @@ revalidate:
- UPDATE_ATIME(inode);
- return 0;
- }
-+
-+#ifdef CONFIG_EXT3_INDEX
-+/*
-+ * These functions convert from the major/minor hash to an f_pos
-+ * value.
-+ *
-+ * Currently we only use major hash numer. This is unfortunate, but
-+ * on 32-bit machines, the same VFS interface is used for lseek and
-+ * llseek, so if we use the 64 bit offset, then the 32-bit versions of
-+ * lseek/telldir/seekdir will blow out spectacularly, and from within
-+ * the ext2 low-level routine, we don't know if we're being called by
-+ * a 64-bit version of the system call or the 32-bit version of the
-+ * system call. Worse yet, NFSv2 only allows for a 32-bit readdir
-+ * cookie. Sigh.
-+ */
-+#define hash2pos(major, minor) (major >> 1)
-+#define pos2maj_hash(pos) ((pos << 1) & 0xffffffff)
-+#define pos2min_hash(pos) (0)
-+
-+/*
-+ * This structure holds the nodes of the red-black tree used to store
-+ * the directory entry in hash order.
-+ */
-+struct fname {
-+ __u32 hash;
-+ __u32 minor_hash;
-+ rb_node_t rb_hash;
-+ struct fname *next;
-+ __u32 inode;
-+ __u8 name_len;
-+ __u8 file_type;
-+ char name[0];
-+};
-+
-+/*
-+ * This functoin implements a non-recursive way of freeing all of the
-+ * nodes in the red-black tree.
-+ */
-+static void free_rb_tree_fname(rb_root_t *root)
-+{
-+ rb_node_t *n = root->rb_node;
-+ rb_node_t *parent;
-+ struct fname *fname;
-+
-+ while (n) {
-+ /* Do the node's children first */
-+ if ((n)->rb_left) {
-+ n = n->rb_left;
-+ continue;
-+ }
-+ if (n->rb_right) {
-+ n = n->rb_right;
-+ continue;
-+ }
-+ /*
-+ * The node has no children; free it, and then zero
-+ * out parent's link to it. Finally go to the
-+ * beginning of the loop and try to free the parent
-+ * node.
-+ */
-+ parent = n->rb_parent;
-+ fname = rb_entry(n, struct fname, rb_hash);
-+ kfree(fname);
-+ if (!parent)
-+ root->rb_node = 0;
-+ else if (parent->rb_left == n)
-+ parent->rb_left = 0;
-+ else if (parent->rb_right == n)
-+ parent->rb_right = 0;
-+ n = parent;
-+ }
-+ root->rb_node = 0;
-+}
-+
-+
-+struct dir_private_info *create_dir_info(loff_t pos)
-+{
-+ struct dir_private_info *p;
-+
-+ p = kmalloc(sizeof(struct dir_private_info), GFP_KERNEL);
-+ if (!p)
-+ return NULL;
-+ p->root.rb_node = 0;
-+ p->curr_node = 0;
-+ p->extra_fname = 0;
-+ p->last_pos = 0;
-+ p->curr_hash = pos2maj_hash(pos);
-+ p->curr_minor_hash = pos2min_hash(pos);
-+ p->next_hash = 0;
-+ return p;
-+}
-+
-+void ext3_htree_free_dir_info(struct dir_private_info *p)
-+{
-+ free_rb_tree_fname(&p->root);
-+ kfree(p);
-+}
-+
-+/*
-+ * Given a directory entry, enter it into the fname rb tree.
-+ */
-+int ext3_htree_store_dirent(struct file *dir_file, __u32 hash,
-+ __u32 minor_hash,
-+ struct ext3_dir_entry_2 *dirent)
-+{
-+ rb_node_t **p, *parent = NULL;
-+ struct fname * fname, *new_fn;
-+ struct dir_private_info *info;
-+ int len;
-+
-+ info = (struct dir_private_info *) dir_file->private_data;
-+ p = &info->root.rb_node;
-+
-+ /* Create and allocate the fname structure */
-+ len = sizeof(struct fname) + dirent->name_len + 1;
-+ new_fn = kmalloc(len, GFP_KERNEL);
-+ if (!new_fn)
-+ return -ENOMEM;
-+ memset(new_fn, 0, len);
-+ new_fn->hash = hash;
-+ new_fn->minor_hash = minor_hash;
-+ new_fn->inode = le32_to_cpu(dirent->inode);
-+ new_fn->name_len = dirent->name_len;
-+ new_fn->file_type = dirent->file_type;
-+ memcpy(new_fn->name, dirent->name, dirent->name_len);
-+ new_fn->name[dirent->name_len] = 0;
-+
-+ while (*p) {
-+ parent = *p;
-+ fname = rb_entry(parent, struct fname, rb_hash);
-+
-+ /*
-+ * If the hash and minor hash match up, then we put
-+ * them on a linked list. This rarely happens...
-+ */
-+ if ((new_fn->hash == fname->hash) &&
-+ (new_fn->minor_hash == fname->minor_hash)) {
-+ new_fn->next = fname->next;
-+ fname->next = new_fn;
-+ return 0;
-+ }
-+
-+ if (new_fn->hash < fname->hash)
-+ p = &(*p)->rb_left;
-+ else if (new_fn->hash > fname->hash)
-+ p = &(*p)->rb_right;
-+ else if (new_fn->minor_hash < fname->minor_hash)
-+ p = &(*p)->rb_left;
-+ else /* if (new_fn->minor_hash > fname->minor_hash) */
-+ p = &(*p)->rb_right;
-+ }
-+
-+ rb_link_node(&new_fn->rb_hash, parent, p);
-+ rb_insert_color(&new_fn->rb_hash, &info->root);
-+ return 0;
-+}
-+
-+
-+
-+/*
-+ * This is a helper function for ext3_dx_readdir. It calls filldir
-+ * for all entres on the fname linked list. (Normally there is only
-+ * one entry on the linked list, unless there are 62 bit hash collisions.)
-+ */
-+static int call_filldir(struct file * filp, void * dirent,
-+ filldir_t filldir, struct fname *fname)
-+{
-+ struct dir_private_info *info = filp->private_data;
-+ loff_t curr_pos;
-+ struct inode *inode = filp->f_dentry->d_inode;
-+ struct super_block * sb;
-+ int error;
-+
-+ sb = inode->i_sb;
-+
-+ if (!fname) {
-+ printk("call_filldir: called with null fname?!?\n");
-+ return 0;
-+ }
-+ curr_pos = hash2pos(fname->hash, fname->minor_hash);
-+ while (fname) {
-+ error = filldir(dirent, fname->name,
-+ fname->name_len, curr_pos,
-+ fname->inode,
-+ get_dtype(sb, fname->file_type));
-+ if (error) {
-+ filp->f_pos = curr_pos;
-+ info->extra_fname = fname->next;
-+ return error;
-+ }
-+ fname = fname->next;
-+ }
-+ return 0;
-+}
-+
-+static int ext3_dx_readdir(struct file * filp,
-+ void * dirent, filldir_t filldir)
-+{
-+ struct dir_private_info *info = filp->private_data;
-+ struct inode *inode = filp->f_dentry->d_inode;
-+ struct fname *fname;
-+ int ret;
-+
-+ if (!info) {
-+ info = create_dir_info(filp->f_pos);
-+ if (!info)
-+ return -ENOMEM;
-+ filp->private_data = info;
-+ }
-+
-+ /* Some one has messed with f_pos; reset the world */
-+ if (info->last_pos != filp->f_pos) {
-+ free_rb_tree_fname(&info->root);
-+ info->curr_node = 0;
-+ info->extra_fname = 0;
-+ info->curr_hash = pos2maj_hash(filp->f_pos);
-+ info->curr_minor_hash = pos2min_hash(filp->f_pos);
-+ }
-+
-+ /*
-+ * If there are any leftover names on the hash collision
-+ * chain, return them first.
-+ */
-+ if (info->extra_fname &&
-+ call_filldir(filp, dirent, filldir, info->extra_fname))
-+ goto finished;
-+
-+ if (!info->curr_node)
-+ info->curr_node = rb_get_first(&info->root);
-+
-+ while (1) {
-+ /*
-+ * Fill the rbtree if we have no more entries,
-+ * or the inode has changed since we last read in the
-+ * cached entries.
-+ */
-+ if ((!info->curr_node) ||
-+ (filp->f_version != inode->i_version)) {
-+ info->curr_node = 0;
-+ free_rb_tree_fname(&info->root);
-+ filp->f_version = inode->i_version;
-+ ret = ext3_htree_fill_tree(filp, info->curr_hash,
-+ info->curr_minor_hash,
-+ &info->next_hash);
-+ if (ret < 0)
-+ return ret;
-+ if (ret == 0)
-+ break;
-+ info->curr_node = rb_get_first(&info->root);
-+ }
-+
-+ fname = rb_entry(info->curr_node, struct fname, rb_hash);
-+ info->curr_hash = fname->hash;
-+ info->curr_minor_hash = fname->minor_hash;
-+ if (call_filldir(filp, dirent, filldir, fname))
-+ break;
-+
-+ info->curr_node = rb_get_next(info->curr_node);
-+ if (!info->curr_node) {
-+ info->curr_hash = info->next_hash;
-+ info->curr_minor_hash = 0;
-+ }
-+ }
-+finished:
-+ info->last_pos = filp->f_pos;
-+ UPDATE_ATIME(inode);
-+ return 0;
-+}
-+#endif
---- linux-2.4.22-ac1/fs/ext3/file.c~ext3-htree-2.4.22-rh 2003-08-25 15:44:43.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext3/file.c 2003-09-25 14:55:12.000000000 +0400
-@@ -35,6 +35,9 @@ static int ext3_release_file (struct ino
- {
- if (filp->f_mode & FMODE_WRITE)
- ext3_discard_prealloc (inode);
-+ if (is_dx(inode) && filp->private_data)
-+ ext3_htree_free_dir_info(filp->private_data);
-+
- return 0;
- }
-
---- /dev/null 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.22-ac1-alexey/fs/ext3/hash.c 2003-09-25 14:55:12.000000000 +0400
-@@ -0,0 +1,215 @@
-+/*
-+ * linux/fs/ext3/hash.c
-+ *
-+ * Copyright (C) 2002 by Theodore Ts'o
-+ *
-+ * This file is released under the GPL v2.
-+ *
-+ * This file may be redistributed under the terms of the GNU Public
-+ * License.
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/jbd.h>
-+#include <linux/sched.h>
-+#include <linux/ext3_fs.h>
-+
-+#define DELTA 0x9E3779B9
-+
-+static void TEA_transform(__u32 buf[4], __u32 const in[])
-+{
-+ __u32 sum = 0;
-+ __u32 b0 = buf[0], b1 = buf[1];
-+ __u32 a = in[0], b = in[1], c = in[2], d = in[3];
-+ int n = 16;
-+
-+ do {
-+ sum += DELTA;
-+ b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
-+ b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
-+ } while(--n);
-+
-+ buf[0] += b0;
-+ buf[1] += b1;
-+}
-+
-+/* F, G and H are basic MD4 functions: selection, majority, parity */
-+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
-+#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
-+#define H(x, y, z) ((x) ^ (y) ^ (z))
-+
-+/*
-+ * The generic round function. The application is so specific that
-+ * we don't bother protecting all the arguments with parens, as is generally
-+ * good macro practice, in favor of extra legibility.
-+ * Rotation is separate from addition to prevent recomputation
-+ */
-+#define ROUND(f, a, b, c, d, x, s) \
-+ (a += f(b, c, d) + x, a = (a << s) | (a >> (32-s)))
-+#define K1 0
-+#define K2 013240474631UL
-+#define K3 015666365641UL
-+
-+/*
-+ * Basic cut-down MD4 transform. Returns only 32 bits of result.
-+ */
-+static void halfMD4Transform (__u32 buf[4], __u32 const in[])
-+{
-+ __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
-+
-+ /* Round 1 */
-+ ROUND(F, a, b, c, d, in[0] + K1, 3);
-+ ROUND(F, d, a, b, c, in[1] + K1, 7);
-+ ROUND(F, c, d, a, b, in[2] + K1, 11);
-+ ROUND(F, b, c, d, a, in[3] + K1, 19);
-+ ROUND(F, a, b, c, d, in[4] + K1, 3);
-+ ROUND(F, d, a, b, c, in[5] + K1, 7);
-+ ROUND(F, c, d, a, b, in[6] + K1, 11);
-+ ROUND(F, b, c, d, a, in[7] + K1, 19);
-+
-+ /* Round 2 */
-+ ROUND(G, a, b, c, d, in[1] + K2, 3);
-+ ROUND(G, d, a, b, c, in[3] + K2, 5);
-+ ROUND(G, c, d, a, b, in[5] + K2, 9);
-+ ROUND(G, b, c, d, a, in[7] + K2, 13);
-+ ROUND(G, a, b, c, d, in[0] + K2, 3);
-+ ROUND(G, d, a, b, c, in[2] + K2, 5);
-+ ROUND(G, c, d, a, b, in[4] + K2, 9);
-+ ROUND(G, b, c, d, a, in[6] + K2, 13);
-+
-+ /* Round 3 */
-+ ROUND(H, a, b, c, d, in[3] + K3, 3);
-+ ROUND(H, d, a, b, c, in[7] + K3, 9);
-+ ROUND(H, c, d, a, b, in[2] + K3, 11);
-+ ROUND(H, b, c, d, a, in[6] + K3, 15);
-+ ROUND(H, a, b, c, d, in[1] + K3, 3);
-+ ROUND(H, d, a, b, c, in[5] + K3, 9);
-+ ROUND(H, c, d, a, b, in[0] + K3, 11);
-+ ROUND(H, b, c, d, a, in[4] + K3, 15);
-+
-+ buf[0] += a;
-+ buf[1] += b;
-+ buf[2] += c;
-+ buf[3] += d;
-+}
-+
-+#undef ROUND
-+#undef F
-+#undef G
-+#undef H
-+#undef K1
-+#undef K2
-+#undef K3
-+
-+/* The old legacy hash */
-+static __u32 dx_hack_hash (const char *name, int len)
-+{
-+ __u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
-+ while (len--) {
-+ __u32 hash = hash1 + (hash0 ^ (*name++ * 7152373));
-+
-+ if (hash & 0x80000000) hash -= 0x7fffffff;
-+ hash1 = hash0;
-+ hash0 = hash;
-+ }
-+ return (hash0 << 1);
-+}
-+
-+static void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
-+{
-+ __u32 pad, val;
-+ int i;
-+
-+ pad = (__u32)len | ((__u32)len << 8);
-+ pad |= pad << 16;
-+
-+ val = pad;
-+ if (len > num*4)
-+ len = num * 4;
-+ for (i=0; i < len; i++) {
-+ if ((i % 4) == 0)
-+ val = pad;
-+ val = msg[i] + (val << 8);
-+ if ((i % 4) == 3) {
-+ *buf++ = val;
-+ val = pad;
-+ num--;
-+ }
-+ }
-+ if (--num >= 0)
-+ *buf++ = val;
-+ while (--num >= 0)
-+ *buf++ = pad;
-+}
-+
-+/*
-+ * Returns the hash of a filename. If len is 0 and name is NULL, then
-+ * this function can be used to test whether or not a hash version is
-+ * supported.
-+ *
-+ * The seed is an 4 longword (32 bits) "secret" which can be used to
-+ * uniquify a hash. If the seed is all zero's, then some default seed
-+ * may be used.
-+ *
-+ * A particular hash version specifies whether or not the seed is
-+ * represented, and whether or not the returned hash is 32 bits or 64
-+ * bits. 32 bit hashes will return 0 for the minor hash.
-+ */
-+int ext3fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
-+{
-+ __u32 hash;
-+ __u32 minor_hash = 0;
-+ const char *p;
-+ int i;
-+ __u32 in[8], buf[4];
-+
-+ /* Initialize the default seed for the hash checksum functions */
-+ buf[0] = 0x67452301;
-+ buf[1] = 0xefcdab89;
-+ buf[2] = 0x98badcfe;
-+ buf[3] = 0x10325476;
-+
-+ /* Check to see if the seed is all zero's */
-+ if (hinfo->seed) {
-+ for (i=0; i < 4; i++) {
-+ if (hinfo->seed[i])
-+ break;
-+ }
-+ if (i < 4)
-+ memcpy(buf, hinfo->seed, sizeof(buf));
-+ }
-+
-+ switch (hinfo->hash_version) {
-+ case DX_HASH_LEGACY:
-+ hash = dx_hack_hash(name, len);
-+ break;
-+ case DX_HASH_HALF_MD4:
-+ p = name;
-+ while (len > 0) {
-+ str2hashbuf(p, len, in, 8);
-+ halfMD4Transform(buf, in);
-+ len -= 32;
-+ p += 32;
-+ }
-+ minor_hash = buf[2];
-+ hash = buf[1];
-+ break;
-+ case DX_HASH_TEA:
-+ p = name;
-+ while (len > 0) {
-+ str2hashbuf(p, len, in, 4);
-+ TEA_transform(buf, in);
-+ len -= 16;
-+ p += 16;
-+ }
-+ hash = buf[0];
-+ minor_hash = buf[1];
-+ break;
-+ default:
-+ hinfo->hash = 0;
-+ return -1;
-+ }
-+ hinfo->hash = hash & ~1;
-+ hinfo->minor_hash = minor_hash;
-+ return 0;
-+}
---- linux-2.4.22-ac1/fs/ext3/Makefile~ext3-htree-2.4.22-rh 2003-09-25 14:39:01.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext3/Makefile 2003-09-25 14:55:12.000000000 +0400
-@@ -12,7 +12,7 @@ O_TARGET := ext3.o
- export-objs := super.o inode.o
-
- obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
-- ioctl.o namei.o super.o symlink.o
-+ ioctl.o namei.o super.o symlink.o hash.o
- obj-m := $(O_TARGET)
-
- include $(TOPDIR)/Rules.make
---- linux-2.4.22-ac1/fs/ext3/namei.c~ext3-htree-2.4.22-rh 2003-09-25 14:16:29.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext3/namei.c 2003-09-25 14:58:37.000000000 +0400
-@@ -16,6 +16,12 @@
- * David S. Miller (davem@caip.rutgers.edu), 1995
- * Directory entry file type support and forward compatibility hooks
- * for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998
-+ * Hash Tree Directory indexing (c)
-+ * Daniel Phillips, 2001
-+ * Hash Tree Directory indexing porting
-+ * Christopher Li, 2002
-+ * Hash Tree Directory indexing cleanup
-+ * Theodore Ts'o, 2002
- */
-
- #include <linux/fs.h>
-@@ -38,6 +44,642 @@
- #define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
- #define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b))
-
-+static struct buffer_head *ext3_append(handle_t *handle,
-+ struct inode *inode,
-+ u32 *block, int *err)
-+{
-+ struct buffer_head *bh;
-+
-+ *block = inode->i_size >> inode->i_sb->s_blocksize_bits;
-+
-+ if ((bh = ext3_bread(handle, inode, *block, 1, err))) {
-+ inode->i_size += inode->i_sb->s_blocksize;
-+ EXT3_I(inode)->i_disksize = inode->i_size;
-+ ext3_journal_get_write_access(handle,bh);
-+ }
-+ return bh;
-+}
-+
-+#ifndef assert
-+#define assert(test) J_ASSERT(test)
-+#endif
-+
-+#ifndef swap
-+#define swap(x, y) do { typeof(x) z = x; x = y; y = z; } while (0)
-+#endif
-+
-+typedef struct { u32 v; } le_u32;
-+typedef struct { u16 v; } le_u16;
-+
-+#ifdef DX_DEBUG
-+#define dxtrace(command) command
-+#else
-+#define dxtrace(command)
-+#endif
-+
-+struct fake_dirent
-+{
-+ /*le*/u32 inode;
-+ /*le*/u16 rec_len;
-+ u8 name_len;
-+ u8 file_type;
-+};
-+
-+struct dx_countlimit
-+{
-+ le_u16 limit;
-+ le_u16 count;
-+};
-+
-+struct dx_entry
-+{
-+ le_u32 hash;
-+ le_u32 block;
-+};
-+
-+/*
-+ * dx_root_info is laid out so that if it should somehow get overlaid by a
-+ * dirent the two low bits of the hash version will be zero. Therefore, the
-+ * hash version mod 4 should never be 0. Sincerely, the paranoia department.
-+ */
-+
-+struct dx_root
-+{
-+ struct fake_dirent dot;
-+ char dot_name[4];
-+ struct fake_dirent dotdot;
-+ char dotdot_name[4];
-+ struct dx_root_info
-+ {
-+ le_u32 reserved_zero;
-+ u8 hash_version;
-+ u8 info_length; /* 8 */
-+ u8 indirect_levels;
-+ u8 unused_flags;
-+ }
-+ info;
-+ struct dx_entry entries[0];
-+};
-+
-+struct dx_node
-+{
-+ struct fake_dirent fake;
-+ struct dx_entry entries[0];
-+};
-+
-+
-+struct dx_frame
-+{
-+ struct buffer_head *bh;
-+ struct dx_entry *entries;
-+ struct dx_entry *at;
-+};
-+
-+struct dx_map_entry
-+{
-+ u32 hash;
-+ u32 offs;
-+};
-+
-+#ifdef CONFIG_EXT3_INDEX
-+static inline unsigned dx_get_block (struct dx_entry *entry);
-+static void dx_set_block (struct dx_entry *entry, unsigned value);
-+static inline unsigned dx_get_hash (struct dx_entry *entry);
-+static void dx_set_hash (struct dx_entry *entry, unsigned value);
-+static unsigned dx_get_count (struct dx_entry *entries);
-+static unsigned dx_get_limit (struct dx_entry *entries);
-+static void dx_set_count (struct dx_entry *entries, unsigned value);
-+static void dx_set_limit (struct dx_entry *entries, unsigned value);
-+static unsigned dx_root_limit (struct inode *dir, unsigned infosize);
-+static unsigned dx_node_limit (struct inode *dir);
-+static struct dx_frame *dx_probe(struct dentry *dentry,
-+ struct inode *dir,
-+ struct dx_hash_info *hinfo,
-+ struct dx_frame *frame,
-+ int *err);
-+static void dx_release (struct dx_frame *frames);
-+static int dx_make_map (struct ext3_dir_entry_2 *de, int size,
-+ struct dx_hash_info *hinfo, struct dx_map_entry map[]);
-+static void dx_sort_map(struct dx_map_entry *map, unsigned count);
-+static struct ext3_dir_entry_2 *dx_move_dirents (char *from, char *to,
-+ struct dx_map_entry *offsets, int count);
-+static struct ext3_dir_entry_2* dx_pack_dirents (char *base, int size);
-+static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block);
-+static int ext3_htree_next_block(struct inode *dir, __u32 hash,
-+ struct dx_frame *frame,
-+ struct dx_frame *frames, int *err,
-+ __u32 *start_hash);
-+static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
-+ struct ext3_dir_entry_2 **res_dir, int *err);
-+static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
-+ struct inode *inode);
-+
-+/*
-+ * Future: use high four bits of block for coalesce-on-delete flags
-+ * Mask them off for now.
-+ */
-+
-+static inline unsigned dx_get_block (struct dx_entry *entry)
-+{
-+ return le32_to_cpu(entry->block.v) & 0x00ffffff;
-+}
-+
-+static inline void dx_set_block (struct dx_entry *entry, unsigned value)
-+{
-+ entry->block.v = cpu_to_le32(value);
-+}
-+
-+static inline unsigned dx_get_hash (struct dx_entry *entry)
-+{
-+ return le32_to_cpu(entry->hash.v);
-+}
-+
-+static inline void dx_set_hash (struct dx_entry *entry, unsigned value)
-+{
-+ entry->hash.v = cpu_to_le32(value);
-+}
-+
-+static inline unsigned dx_get_count (struct dx_entry *entries)
-+{
-+ return le16_to_cpu(((struct dx_countlimit *) entries)->count.v);
-+}
-+
-+static inline unsigned dx_get_limit (struct dx_entry *entries)
-+{
-+ return le16_to_cpu(((struct dx_countlimit *) entries)->limit.v);
-+}
-+
-+static inline void dx_set_count (struct dx_entry *entries, unsigned value)
-+{
-+ ((struct dx_countlimit *) entries)->count.v = cpu_to_le16(value);
-+}
-+
-+static inline void dx_set_limit (struct dx_entry *entries, unsigned value)
-+{
-+ ((struct dx_countlimit *) entries)->limit.v = cpu_to_le16(value);
-+}
-+
-+static inline unsigned dx_root_limit (struct inode *dir, unsigned infosize)
-+{
-+ unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(1) -
-+ EXT3_DIR_REC_LEN(2) - infosize;
-+ return 0? 20: entry_space / sizeof(struct dx_entry);
-+}
-+
-+static inline unsigned dx_node_limit (struct inode *dir)
-+{
-+ unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(0);
-+ return 0? 22: entry_space / sizeof(struct dx_entry);
-+}
-+
-+/*
-+ * Debug
-+ */
-+#ifdef DX_DEBUG
-+struct stats
-+{
-+ unsigned names;
-+ unsigned space;
-+ unsigned bcount;
-+};
-+
-+static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext3_dir_entry_2 *de,
-+ int size, int show_names)
-+{
-+ unsigned names = 0, space = 0;
-+ char *base = (char *) de;
-+ struct dx_hash_info h = *hinfo;
-+
-+ printk("names: ");
-+ while ((char *) de < base + size)
-+ {
-+ if (de->inode)
-+ {
-+ if (show_names)
-+ {
-+ int len = de->name_len;
-+ char *name = de->name;
-+ while (len--) printk("%c", *name++);
-+ ext3fs_dirhash(de->name, de->name_len, &h);
-+ printk(":%x.%u ", h.hash,
-+ ((char *) de - base));
-+ }
-+ space += EXT3_DIR_REC_LEN(de->name_len);
-+ names++;
-+ }
-+ de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
-+ }
-+ printk("(%i)\n", names);
-+ return (struct stats) { names, space, 1 };
-+}
-+
-+struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
-+ struct dx_entry *entries, int levels)
-+{
-+ unsigned blocksize = dir->i_sb->s_blocksize;
-+ unsigned count = dx_get_count (entries), names = 0, space = 0, i;
-+ unsigned bcount = 0;
-+ struct buffer_head *bh;
-+ int err;
-+ printk("%i indexed blocks...\n", count);
-+ for (i = 0; i < count; i++, entries++)
-+ {
-+ u32 block = dx_get_block(entries), hash = i? dx_get_hash(entries): 0;
-+ u32 range = i < count - 1? (dx_get_hash(entries + 1) - hash): ~hash;
-+ struct stats stats;
-+ printk("%s%3u:%03u hash %8x/%8x ",levels?"":" ", i, block, hash, range);
-+ if (!(bh = ext3_bread (NULL,dir, block, 0,&err))) continue;
-+ stats = levels?
-+ dx_show_entries(hinfo, dir, ((struct dx_node *) bh->b_data)->entries, levels - 1):
-+ dx_show_leaf(hinfo, (struct ext3_dir_entry_2 *) bh->b_data, blocksize, 0);
-+ names += stats.names;
-+ space += stats.space;
-+ bcount += stats.bcount;
-+ brelse (bh);
-+ }
-+ if (bcount)
-+ printk("%snames %u, fullness %u (%u%%)\n", levels?"":" ",
-+ names, space/bcount,(space/bcount)*100/blocksize);
-+ return (struct stats) { names, space, bcount};
-+}
-+#endif /* DX_DEBUG */
-+
-+/*
-+ * Probe for a directory leaf block to search.
-+ *
-+ * dx_probe can return ERR_BAD_DX_DIR, which means there was a format
-+ * error in the directory index, and the caller should fall back to
-+ * searching the directory normally. The callers of dx_probe **MUST**
-+ * check for this error code, and make sure it never gets reflected
-+ * back to userspace.
-+ */
-+static struct dx_frame *
-+dx_probe(struct dentry *dentry, struct inode *dir,
-+ struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err)
-+{
-+ unsigned count, indirect;
-+ struct dx_entry *at, *entries, *p, *q, *m;
-+ struct dx_root *root;
-+ struct buffer_head *bh;
-+ struct dx_frame *frame = frame_in;
-+ u32 hash;
-+
-+ frame->bh = NULL;
-+ if (dentry)
-+ dir = dentry->d_parent->d_inode;
-+ if (!(bh = ext3_bread (NULL,dir, 0, 0, err)))
-+ goto fail;
-+ root = (struct dx_root *) bh->b_data;
-+ if (root->info.hash_version != DX_HASH_TEA &&
-+ root->info.hash_version != DX_HASH_HALF_MD4 &&
-+ root->info.hash_version != DX_HASH_LEGACY) {
-+ ext3_warning(dir->i_sb, __FUNCTION__,
-+ "Unrecognised inode hash code %d",
-+ root->info.hash_version);
-+ brelse(bh);
-+ *err = ERR_BAD_DX_DIR;
-+ goto fail;
-+ }
-+ hinfo->hash_version = root->info.hash_version;
-+ hinfo->seed = dir->i_sb->u.ext3_sb.s_hash_seed;
-+ if (dentry)
-+ ext3fs_dirhash(dentry->d_name.name, dentry->d_name.len, hinfo);
-+ hash = hinfo->hash;
-+
-+ if (root->info.unused_flags & 1) {
-+ ext3_warning(dir->i_sb, __FUNCTION__,
-+ "Unimplemented inode hash flags: %#06x",
-+ root->info.unused_flags);
-+ brelse(bh);
-+ *err = ERR_BAD_DX_DIR;
-+ goto fail;
-+ }
-+
-+ if ((indirect = root->info.indirect_levels) > 1) {
-+ ext3_warning(dir->i_sb, __FUNCTION__,
-+ "Unimplemented inode hash depth: %#06x",
-+ root->info.indirect_levels);
-+ brelse(bh);
-+ *err = ERR_BAD_DX_DIR;
-+ goto fail;
-+ }
-+
-+ entries = (struct dx_entry *) (((char *)&root->info) +
-+ root->info.info_length);
-+ assert(dx_get_limit(entries) == dx_root_limit(dir,
-+ root->info.info_length));
-+ dxtrace (printk("Look up %x", hash));
-+ while (1)
-+ {
-+ count = dx_get_count(entries);
-+ assert (count && count <= dx_get_limit(entries));
-+ p = entries + 1;
-+ q = entries + count - 1;
-+ while (p <= q)
-+ {
-+ m = p + (q - p)/2;
-+ dxtrace(printk("."));
-+ if (dx_get_hash(m) > hash)
-+ q = m - 1;
-+ else
-+ p = m + 1;
-+ }
-+
-+ if (0) // linear search cross check
-+ {
-+ unsigned n = count - 1;
-+ at = entries;
-+ while (n--)
-+ {
-+ dxtrace(printk(","));
-+ if (dx_get_hash(++at) > hash)
-+ {
-+ at--;
-+ break;
-+ }
-+ }
-+ assert (at == p - 1);
-+ }
-+
-+ at = p - 1;
-+ dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at)));
-+ frame->bh = bh;
-+ frame->entries = entries;
-+ frame->at = at;
-+ if (!indirect--) return frame;
-+ if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err)))
-+ goto fail2;
-+ at = entries = ((struct dx_node *) bh->b_data)->entries;
-+ assert (dx_get_limit(entries) == dx_node_limit (dir));
-+ frame++;
-+ }
-+fail2:
-+ while (frame >= frame_in) {
-+ brelse(frame->bh);
-+ frame--;
-+ }
-+fail:
-+ return NULL;
-+}
-+
-+static void dx_release (struct dx_frame *frames)
-+{
-+ if (frames[0].bh == NULL)
-+ return;
-+
-+ if (((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels)
-+ brelse(frames[1].bh);
-+ brelse(frames[0].bh);
-+}
-+
-+/*
-+ * This function increments the frame pointer to search the next leaf
-+ * block, and reads in the necessary intervening nodes if the search
-+ * should be necessary. Whether or not the search is necessary is
-+ * controlled by the hash parameter. If the hash value is even, then
-+ * the search is only continued if the next block starts with that
-+ * hash value. This is used if we are searching for a specific file.
-+ *
-+ * If the hash value is HASH_NB_ALWAYS, then always go to the next block.
-+ *
-+ * This function returns 1 if the caller should continue to search,
-+ * or 0 if it should not. If there is an error reading one of the
-+ * index blocks, it will return -1.
-+ *
-+ * If start_hash is non-null, it will be filled in with the starting
-+ * hash of the next page.
-+ */
-+static int ext3_htree_next_block(struct inode *dir, __u32 hash,
-+ struct dx_frame *frame,
-+ struct dx_frame *frames, int *err,
-+ __u32 *start_hash)
-+{
-+ struct dx_frame *p;
-+ struct buffer_head *bh;
-+ int num_frames = 0;
-+ __u32 bhash;
-+
-+ *err = ENOENT;
-+ p = frame;
-+ /*
-+ * Find the next leaf page by incrementing the frame pointer.
-+ * If we run out of entries in the interior node, loop around and
-+ * increment pointer in the parent node. When we break out of
-+ * this loop, num_frames indicates the number of interior
-+ * nodes need to be read.
-+ */
-+ while (1) {
-+ if (++(p->at) < p->entries + dx_get_count(p->entries))
-+ break;
-+ if (p == frames)
-+ return 0;
-+ num_frames++;
-+ p--;
-+ }
-+
-+ /*
-+ * If the hash is 1, then continue only if the next page has a
-+ * continuation hash of any value. This is used for readdir
-+ * handling. Otherwise, check to see if the hash matches the
-+ * desired contiuation hash. If it doesn't, return since
-+ * there's no point to read in the successive index pages.
-+ */
-+ bhash = dx_get_hash(p->at);
-+ if (start_hash)
-+ *start_hash = bhash;
-+ if ((hash & 1) == 0) {
-+ if ((bhash & ~1) != hash)
-+ return 0;
-+ }
-+ /*
-+ * If the hash is HASH_NB_ALWAYS, we always go to the next
-+ * block so no check is necessary
-+ */
-+ while (num_frames--) {
-+ if (!(bh = ext3_bread(NULL, dir, dx_get_block(p->at),
-+ 0, err)))
-+ return -1; /* Failure */
-+ p++;
-+ brelse (p->bh);
-+ p->bh = bh;
-+ p->at = p->entries = ((struct dx_node *) bh->b_data)->entries;
-+ }
-+ return 1;
-+}
-+
-+
-+/*
-+ * p is at least 6 bytes before the end of page
-+ */
-+static inline struct ext3_dir_entry_2 *ext3_next_entry(struct ext3_dir_entry_2 *p)
-+{
-+ return (struct ext3_dir_entry_2 *)((char*)p + le16_to_cpu(p->rec_len));
-+}
-+
-+/*
-+ * This function fills a red-black tree with information from a
-+ * directory. We start scanning the directory in hash order, starting
-+ * at start_hash and start_minor_hash.
-+ *
-+ * This function returns the number of entries inserted into the tree,
-+ * or a negative error code.
-+ */
-+int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash,
-+ __u32 start_minor_hash, __u32 *next_hash)
-+{
-+ struct dx_hash_info hinfo;
-+ struct buffer_head *bh;
-+ struct ext3_dir_entry_2 *de, *top;
-+ static struct dx_frame frames[2], *frame;
-+ struct inode *dir;
-+ int block, err;
-+ int count = 0;
-+ int ret;
-+ __u32 hashval;
-+
-+ dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash,
-+ start_minor_hash));
-+ dir = dir_file->f_dentry->d_inode;
-+ hinfo.hash = start_hash;
-+ hinfo.minor_hash = 0;
-+ frame = dx_probe(0, dir_file->f_dentry->d_inode, &hinfo, frames, &err);
-+ if (!frame)
-+ return err;
-+
-+ /* Add '.' and '..' from the htree header */
-+ if (!start_hash && !start_minor_hash) {
-+ de = (struct ext3_dir_entry_2 *) frames[0].bh->b_data;
-+ if ((err = ext3_htree_store_dirent(dir_file, 0, 0, de)) != 0)
-+ goto errout;
-+ de = ext3_next_entry(de);
-+ if ((err = ext3_htree_store_dirent(dir_file, 0, 0, de)) != 0)
-+ goto errout;
-+ count += 2;
-+ }
-+
-+ while (1) {
-+ block = dx_get_block(frame->at);
-+ dxtrace(printk("Reading block %d\n", block));
-+ if (!(bh = ext3_bread (NULL, dir, block, 0, &err)))
-+ goto errout;
-+
-+ de = (struct ext3_dir_entry_2 *) bh->b_data;
-+ top = (struct ext3_dir_entry_2 *) ((char *) de + dir->i_sb->s_blocksize -
-+ EXT3_DIR_REC_LEN(0));
-+ for (; de < top; de = ext3_next_entry(de)) {
-+ ext3fs_dirhash(de->name, de->name_len, &hinfo);
-+ if ((hinfo.hash < start_hash) ||
-+ ((hinfo.hash == start_hash) &&
-+ (hinfo.minor_hash < start_minor_hash)))
-+ continue;
-+ if ((err = ext3_htree_store_dirent(dir_file,
-+ hinfo.hash, hinfo.minor_hash, de)) != 0)
-+ goto errout;
-+ count++;
-+ }
-+ brelse (bh);
-+ hashval = ~1;
-+ ret = ext3_htree_next_block(dir, HASH_NB_ALWAYS,
-+ frame, frames, &err, &hashval);
-+ if (next_hash)
-+ *next_hash = hashval;
-+ if (ret == -1)
-+ goto errout;
-+ /*
-+ * Stop if: (a) there are no more entries, or
-+ * (b) we have inserted at least one entry and the
-+ * next hash value is not a continuation
-+ */
-+ if ((ret == 0) ||
-+ (count && ((hashval & 1) == 0)))
-+ break;
-+ }
-+ dx_release(frames);
-+ dxtrace(printk("Fill tree: returned %d entries\n", count));
-+ return count;
-+errout:
-+ dx_release(frames);
-+ return (err);
-+}
-+
-+
-+/*
-+ * Directory block splitting, compacting
-+ */
-+
-+static int dx_make_map (struct ext3_dir_entry_2 *de, int size,
-+ struct dx_hash_info *hinfo, struct dx_map_entry *map_tail)
-+{
-+ int count = 0;
-+ char *base = (char *) de;
-+ struct dx_hash_info h = *hinfo;
-+
-+ while ((char *) de < base + size)
-+ {
-+ if (de->name_len && de->inode) {
-+ ext3fs_dirhash(de->name, de->name_len, &h);
-+ map_tail--;
-+ map_tail->hash = h.hash;
-+ map_tail->offs = (u32) ((char *) de - base);
-+ count++;
-+ }
-+ /* XXX: do we need to check rec_len == 0 case? -Chris */
-+ de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
-+ }
-+ return count;
-+}
-+
-+static void dx_sort_map (struct dx_map_entry *map, unsigned count)
-+{
-+ struct dx_map_entry *p, *q, *top = map + count - 1;
-+ int more;
-+ /* Combsort until bubble sort doesn't suck */
-+ while (count > 2)
-+ {
-+ count = count*10/13;
-+ if (count - 9 < 2) /* 9, 10 -> 11 */
-+ count = 11;
-+ for (p = top, q = p - count; q >= map; p--, q--)
-+ if (p->hash < q->hash)
-+ swap(*p, *q);
-+ }
-+ /* Garden variety bubble sort */
-+ do {
-+ more = 0;
-+ q = top;
-+ while (q-- > map)
-+ {
-+ if (q[1].hash >= q[0].hash)
-+ continue;
-+ swap(*(q+1), *q);
-+ more = 1;
-+ }
-+ } while(more);
-+}
-+
-+static void dx_insert_block(struct dx_frame *frame, u32 hash, u32 block)
-+{
-+ struct dx_entry *entries = frame->entries;
-+ struct dx_entry *old = frame->at, *new = old + 1;
-+ int count = dx_get_count(entries);
-+
-+ assert(count < dx_get_limit(entries));
-+ assert(old < entries + count);
-+ memmove(new + 1, new, (char *)(entries + count) - (char *)(new));
-+ dx_set_hash(new, hash);
-+ dx_set_block(new, block);
-+ dx_set_count(entries, count + 1);
-+}
-+#endif
-+
-+
-+static void ext3_update_dx_flag(struct inode *inode)
-+{
-+ if (!EXT3_HAS_COMPAT_FEATURE(inode->i_sb,
-+ EXT3_FEATURE_COMPAT_DIR_INDEX))
-+ EXT3_I(inode)->i_flags &= ~EXT3_INDEX_FL;
-+}
-+
- /*
- * NOTE! unlike strncmp, ext3_match returns 1 for success, 0 for failure.
- *
-@@ -94,6 +736,7 @@ static int inline search_dirblock(struct
- return 0;
- }
-
-+
- /*
- * ext3_find_entry()
- *
-@@ -105,6 +748,8 @@ static int inline search_dirblock(struct
- * The returned buffer_head has ->b_count elevated. The caller is expected
- * to brelse() it when appropriate.
- */
-+
-+
- static struct buffer_head * ext3_find_entry (struct dentry *dentry,
- struct ext3_dir_entry_2 ** res_dir)
- {
-@@ -119,12 +764,32 @@ static struct buffer_head * ext3_find_en
- int num = 0;
- int nblocks, i, err;
- struct inode *dir = dentry->d_parent->d_inode;
-+ int namelen;
-+ const u8 *name;
-+ unsigned blocksize;
-
- *res_dir = NULL;
- sb = dir->i_sb;
--
-+ blocksize = sb->s_blocksize;
-+ namelen = dentry->d_name.len;
-+ name = dentry->d_name.name;
-+ if (namelen > EXT3_NAME_LEN)
-+ return NULL;
-+#ifdef CONFIG_EXT3_INDEX
-+ if (is_dx(dir)) {
-+ bh = ext3_dx_find_entry(dentry, res_dir, &err);
-+ /*
-+ * On success, or if the error was file not found,
-+ * return. Otherwise, fall back to doing a search the
-+ * old fashioned way.
-+ */
-+ if (bh || (err != ERR_BAD_DX_DIR))
-+ return bh;
-+ dxtrace(printk("ext3_find_entry: dx failed, falling back\n"));
-+ }
-+#endif
- nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb);
-- start = dir->u.ext3_i.i_dir_start_lookup;
-+ start = EXT3_I(dir)->i_dir_start_lookup;
- if (start >= nblocks)
- start = 0;
- block = start;
-@@ -166,7 +831,7 @@ restart:
- i = search_dirblock(bh, dir, dentry,
- block << EXT3_BLOCK_SIZE_BITS(sb), res_dir);
- if (i == 1) {
-- dir->u.ext3_i.i_dir_start_lookup = block;
-+ EXT3_I(dir)->i_dir_start_lookup = block;
- ret = bh;
- goto cleanup_and_exit;
- } else {
-@@ -197,6 +862,66 @@ cleanup_and_exit:
- return ret;
- }
-
-+#ifdef CONFIG_EXT3_INDEX
-+static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
-+ struct ext3_dir_entry_2 **res_dir, int *err)
-+{
-+ struct super_block * sb;
-+ struct dx_hash_info hinfo;
-+ u32 hash;
-+ struct dx_frame frames[2], *frame;
-+ struct ext3_dir_entry_2 *de, *top;
-+ struct buffer_head *bh;
-+ unsigned long block;
-+ int retval;
-+ int namelen = dentry->d_name.len;
-+ const u8 *name = dentry->d_name.name;
-+ struct inode *dir = dentry->d_parent->d_inode;
-+
-+ sb = dir->i_sb;
-+ if (!(frame = dx_probe (dentry, 0, &hinfo, frames, err)))
-+ return NULL;
-+ hash = hinfo.hash;
-+ do {
-+ block = dx_get_block(frame->at);
-+ if (!(bh = ext3_bread (NULL,dir, block, 0, err)))
-+ goto errout;
-+ de = (struct ext3_dir_entry_2 *) bh->b_data;
-+ top = (struct ext3_dir_entry_2 *) ((char *) de + sb->s_blocksize -
-+ EXT3_DIR_REC_LEN(0));
-+ for (; de < top; de = ext3_next_entry(de))
-+ if (ext3_match (namelen, name, de)) {
-+ if (!ext3_check_dir_entry("ext3_find_entry",
-+ dir, de, bh,
-+ (block<<EXT3_BLOCK_SIZE_BITS(sb))
-+ +((char *)de - bh->b_data))) {
-+ brelse (bh);
-+ goto errout;
-+ }
-+ *res_dir = de;
-+ dx_release (frames);
-+ return bh;
-+ }
-+ brelse (bh);
-+ /* Check to see if we should continue to search */
-+ retval = ext3_htree_next_block(dir, hash, frame,
-+ frames, err, 0);
-+ if (retval == -1) {
-+ ext3_warning(sb, __FUNCTION__,
-+ "error reading index page in directory #%lu",
-+ dir->i_ino);
-+ goto errout;
-+ }
-+ } while (retval == 1);
-+
-+ *err = -ENOENT;
-+errout:
-+ dxtrace(printk("%s not found\n", name));
-+ dx_release (frames);
-+ return NULL;
-+}
-+#endif
-+
- static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry)
- {
- struct inode * inode;
-@@ -213,8 +938,9 @@ static struct dentry *ext3_lookup(struct
- brelse (bh);
- inode = iget(dir->i_sb, ino);
-
-- if (!inode)
-+ if (!inode) {
- return ERR_PTR(-EACCES);
-+ }
- }
- d_add(dentry, inode);
- return NULL;
-@@ -238,6 +964,301 @@ static inline void ext3_set_de_type(stru
- de->file_type = ext3_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
- }
-
-+#ifdef CONFIG_EXT3_INDEX
-+static struct ext3_dir_entry_2 *
-+dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count)
-+{
-+ unsigned rec_len = 0;
-+
-+ while (count--) {
-+ struct ext3_dir_entry_2 *de = (struct ext3_dir_entry_2 *) (from + map->offs);
-+ rec_len = EXT3_DIR_REC_LEN(de->name_len);
-+ memcpy (to, de, rec_len);
-+ ((struct ext3_dir_entry_2 *)to)->rec_len = cpu_to_le16(rec_len);
-+ de->inode = 0;
-+ map++;
-+ to += rec_len;
-+ }
-+ return (struct ext3_dir_entry_2 *) (to - rec_len);
-+}
-+
-+static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size)
-+{
-+ struct ext3_dir_entry_2 *next, *to, *prev, *de = (struct ext3_dir_entry_2 *) base;
-+ unsigned rec_len = 0;
-+
-+ prev = to = de;
-+ while ((char*)de < base + size) {
-+ next = (struct ext3_dir_entry_2 *) ((char *) de +
-+ le16_to_cpu(de->rec_len));
-+ if (de->inode && de->name_len) {
-+ rec_len = EXT3_DIR_REC_LEN(de->name_len);
-+ if (de > to)
-+ memmove(to, de, rec_len);
-+ to->rec_len = cpu_to_le16(rec_len);
-+ prev = to;
-+ to = (struct ext3_dir_entry_2 *)((char *)to + rec_len);
-+ }
-+ de = next;
-+ }
-+ return prev;
-+}
-+
-+static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
-+ struct buffer_head **bh,struct dx_frame *frame,
-+ struct dx_hash_info *hinfo, int *error)
-+{
-+ unsigned blocksize = dir->i_sb->s_blocksize;
-+ unsigned count, continued;
-+ struct buffer_head *bh2;
-+ u32 newblock;
-+ u32 hash2;
-+ struct dx_map_entry *map;
-+ char *data1 = (*bh)->b_data, *data2;
-+ unsigned split;
-+ struct ext3_dir_entry_2 *de = NULL, *de2;
-+ int err;
-+
-+ bh2 = ext3_append (handle, dir, &newblock, error);
-+ if (!(bh2)) {
-+ brelse(*bh);
-+ *bh = NULL;
-+ goto errout;
-+ }
-+
-+ BUFFER_TRACE(*bh, "get_write_access");
-+ err = ext3_journal_get_write_access(handle, *bh);
-+ if (err) {
-+ journal_error:
-+ brelse(*bh);
-+ brelse(bh2);
-+ *bh = NULL;
-+ ext3_std_error(dir->i_sb, err);
-+ goto errout;
-+ }
-+ BUFFER_TRACE(frame->bh, "get_write_access");
-+ err = ext3_journal_get_write_access(handle, frame->bh);
-+ if (err)
-+ goto journal_error;
-+
-+ data2 = bh2->b_data;
-+
-+ /* create map in the end of data2 block */
-+ map = (struct dx_map_entry *) (data2 + blocksize);
-+ count = dx_make_map ((struct ext3_dir_entry_2 *) data1,
-+ blocksize, hinfo, map);
-+ map -= count;
-+ split = count/2; // need to adjust to actual middle
-+ dx_sort_map (map, count);
-+ hash2 = map[split].hash;
-+ continued = hash2 == map[split - 1].hash;
-+ dxtrace(printk("Split block %i at %x, %i/%i\n",
-+ dx_get_block(frame->at), hash2, split, count-split));
-+
-+ /* Fancy dance to stay within two buffers */
-+ de2 = dx_move_dirents(data1, data2, map + split, count - split);
-+ de = dx_pack_dirents(data1,blocksize);
-+ de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
-+ de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2);
-+ dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data1, blocksize, 1));
-+ dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data2, blocksize, 1));
-+
-+ /* Which block gets the new entry? */
-+ if (hinfo->hash >= hash2)
-+ {
-+ swap(*bh, bh2);
-+ de = de2;
-+ }
-+ dx_insert_block (frame, hash2 + continued, newblock);
-+ err = ext3_journal_dirty_metadata (handle, bh2);
-+ if (err)
-+ goto journal_error;
-+ err = ext3_journal_dirty_metadata (handle, frame->bh);
-+ if (err)
-+ goto journal_error;
-+ brelse (bh2);
-+ dxtrace(dx_show_index ("frame", frame->entries));
-+errout:
-+ return de;
-+}
-+#endif
-+
-+
-+/*
-+ * Add a new entry into a directory (leaf) block. If de is non-NULL,
-+ * it points to a directory entry which is guaranteed to be large
-+ * enough for new directory entry. If de is NULL, then
-+ * add_dirent_to_buf will attempt search the directory block for
-+ * space. It will return -ENOSPC if no space is available, and -EIO
-+ * and -EEXIST if directory entry already exists.
-+ *
-+ * NOTE! bh is NOT released in the case where ENOSPC is returned. In
-+ * all other cases bh is released.
-+ */
-+static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
-+ struct inode *inode, struct ext3_dir_entry_2 *de,
-+ struct buffer_head * bh)
-+{
-+ struct inode *dir = dentry->d_parent->d_inode;
-+ const char *name = dentry->d_name.name;
-+ int namelen = dentry->d_name.len;
-+ unsigned long offset = 0;
-+ unsigned short reclen;
-+ int nlen, rlen, err;
-+ char *top;
-+
-+ reclen = EXT3_DIR_REC_LEN(namelen);
-+ if (!de) {
-+ de = (struct ext3_dir_entry_2 *)bh->b_data;
-+ top = bh->b_data + dir->i_sb->s_blocksize - reclen;
-+ while ((char *) de <= top) {
-+ if (!ext3_check_dir_entry("ext3_add_entry", dir, de,
-+ bh, offset)) {
-+ brelse (bh);
-+ return -EIO;
-+ }
-+ if (ext3_match (namelen, name, de)) {
-+ brelse (bh);
-+ return -EEXIST;
-+ }
-+ nlen = EXT3_DIR_REC_LEN(de->name_len);
-+ rlen = le16_to_cpu(de->rec_len);
-+ if ((de->inode? rlen - nlen: rlen) >= reclen)
-+ break;
-+ de = (struct ext3_dir_entry_2 *)((char *)de + rlen);
-+ offset += rlen;
-+ }
-+ if ((char *) de > top)
-+ return -ENOSPC;
-+ }
-+ BUFFER_TRACE(bh, "get_write_access");
-+ err = ext3_journal_get_write_access(handle, bh);
-+ if (err) {
-+ ext3_std_error(dir->i_sb, err);
-+ brelse(bh);
-+ return err;
-+ }
-+
-+ /* By now the buffer is marked for journaling */
-+ nlen = EXT3_DIR_REC_LEN(de->name_len);
-+ rlen = le16_to_cpu(de->rec_len);
-+ if (de->inode) {
-+ struct ext3_dir_entry_2 *de1 = (struct ext3_dir_entry_2 *)((char *)de + nlen);
-+ de1->rec_len = cpu_to_le16(rlen - nlen);
-+ de->rec_len = cpu_to_le16(nlen);
-+ de = de1;
-+ }
-+ de->file_type = EXT3_FT_UNKNOWN;
-+ if (inode) {
-+ de->inode = cpu_to_le32(inode->i_ino);
-+ ext3_set_de_type(dir->i_sb, de, inode->i_mode);
-+ } else
-+ de->inode = 0;
-+ de->name_len = namelen;
-+ memcpy (de->name, name, namelen);
-+ /*
-+ * XXX shouldn't update any times until successful
-+ * completion of syscall, but too many callers depend
-+ * on this.
-+ *
-+ * XXX similarly, too many callers depend on
-+ * ext3_new_inode() setting the times, but error
-+ * recovery deletes the inode, so the worst that can
-+ * happen is that the times are slightly out of date
-+ * and/or different from the directory change time.
-+ */
-+ dir->i_mtime = dir->i_ctime = CURRENT_TIME;
-+ ext3_update_dx_flag(dir);
-+ dir->i_version = ++event;
-+ ext3_mark_inode_dirty(handle, dir);
-+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
-+ err = ext3_journal_dirty_metadata(handle, bh);
-+ if (err)
-+ ext3_std_error(dir->i_sb, err);
-+ brelse(bh);
-+ return 0;
-+}
-+
-+#ifdef CONFIG_EXT3_INDEX
-+/*
-+ * This converts a one block unindexed directory to a 3 block indexed
-+ * directory, and adds the dentry to the indexed directory.
-+ */
-+static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
-+ struct inode *inode, struct buffer_head *bh)
-+{
-+ struct inode *dir = dentry->d_parent->d_inode;
-+ const char *name = dentry->d_name.name;
-+ int namelen = dentry->d_name.len;
-+ struct buffer_head *bh2;
-+ struct dx_root *root;
-+ struct dx_frame frames[2], *frame;
-+ struct dx_entry *entries;
-+ struct ext3_dir_entry_2 *de, *de2;
-+ char *data1, *top;
-+ unsigned len;
-+ int retval;
-+ unsigned blocksize;
-+ struct dx_hash_info hinfo;
-+ u32 block;
-+
-+ blocksize = dir->i_sb->s_blocksize;
-+ dxtrace(printk("Creating index\n"));
-+ retval = ext3_journal_get_write_access(handle, bh);
-+ if (retval) {
-+ ext3_std_error(dir->i_sb, retval);
-+ brelse(bh);
-+ return retval;
-+ }
-+ root = (struct dx_root *) bh->b_data;
-+
-+ EXT3_I(dir)->i_flags |= EXT3_INDEX_FL;
-+ bh2 = ext3_append (handle, dir, &block, &retval);
-+ if (!(bh2)) {
-+ brelse(bh);
-+ return retval;
-+ }
-+ data1 = bh2->b_data;
-+
-+ /* The 0th block becomes the root, move the dirents out */
-+ de = (struct ext3_dir_entry_2 *)&root->dotdot;
-+ de = (struct ext3_dir_entry_2 *)((char *)de + le16_to_cpu(de->rec_len));
-+ len = ((char *) root) + blocksize - (char *) de;
-+ memcpy (data1, de, len);
-+ de = (struct ext3_dir_entry_2 *) data1;
-+ top = data1 + len;
-+ while (((char *) de2=(char*)de+le16_to_cpu(de->rec_len)) < top)
-+ de = de2;
-+ de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
-+ /* Initialize the root; the dot dirents already exist */
-+ de = (struct ext3_dir_entry_2 *) (&root->dotdot);
-+ de->rec_len = cpu_to_le16(blocksize - EXT3_DIR_REC_LEN(2));
-+ memset (&root->info, 0, sizeof(root->info));
-+ root->info.info_length = sizeof(root->info);
-+ root->info.hash_version = dir->i_sb->u.ext3_sb.s_def_hash_version;
-+ entries = root->entries;
-+ dx_set_block (entries, 1);
-+ dx_set_count (entries, 1);
-+ dx_set_limit (entries, dx_root_limit(dir, sizeof(root->info)));
-+
-+ /* Initialize as for dx_probe */
-+ hinfo.hash_version = root->info.hash_version;
-+ hinfo.seed = dir->i_sb->u.ext3_sb.s_hash_seed;
-+ ext3fs_dirhash(name, namelen, &hinfo);
-+ frame = frames;
-+ frame->entries = entries;
-+ frame->at = entries;
-+ frame->bh = bh;
-+ bh = bh2;
-+ de = do_split(handle,dir, &bh, frame, &hinfo, &retval);
-+ dx_release (frames);
-+ if (!(de))
-+ return retval;
-+
-+ return add_dirent_to_buf(handle, dentry, inode, de, bh);
-+}
-+#endif
-+
- /*
- * ext3_add_entry()
- *
-@@ -248,127 +1269,198 @@ static inline void ext3_set_de_type(stru
- * may not sleep between calling this and putting something into
- * the entry, as someone else might have used it while you slept.
- */
--
--/*
-- * AKPM: the journalling code here looks wrong on the error paths
-- */
- static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
- struct inode *inode)
- {
- struct inode *dir = dentry->d_parent->d_inode;
-- const char *name = dentry->d_name.name;
-- int namelen = dentry->d_name.len;
- unsigned long offset;
-- unsigned short rec_len;
- struct buffer_head * bh;
-- struct ext3_dir_entry_2 * de, * de1;
-+ struct ext3_dir_entry_2 *de;
- struct super_block * sb;
- int retval;
-+#ifdef CONFIG_EXT3_INDEX
-+ int dx_fallback=0;
-+#endif
-+ unsigned blocksize;
-+ unsigned nlen, rlen;
-+ u32 block, blocks;
-
- sb = dir->i_sb;
--
-- if (!namelen)
-+ blocksize = sb->s_blocksize;
-+ if (!dentry->d_name.len)
- return -EINVAL;
-- bh = ext3_bread (handle, dir, 0, 0, &retval);
-+#ifdef CONFIG_EXT3_INDEX
-+ if (is_dx(dir)) {
-+ retval = ext3_dx_add_entry(handle, dentry, inode);
-+ if (!retval || (retval != ERR_BAD_DX_DIR))
-+ return retval;
-+ EXT3_I(dir)->i_flags &= ~EXT3_INDEX_FL;
-+ dx_fallback++;
-+ ext3_mark_inode_dirty(handle, dir);
-+ }
-+#endif
-+ blocks = dir->i_size >> sb->s_blocksize_bits;
-+ for (block = 0, offset = 0; block < blocks; block++) {
-+ bh = ext3_bread(handle, dir, block, 0, &retval);
-+ if(!bh)
-+ return retval;
-+ retval = add_dirent_to_buf(handle, dentry, inode, 0, bh);
-+ if (retval != -ENOSPC)
-+ return retval;
-+
-+#ifdef CONFIG_EXT3_INDEX
-+ if (blocks == 1 && !dx_fallback &&
-+ EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX))
-+ return make_indexed_dir(handle, dentry, inode, bh);
-+#endif
-+ brelse(bh);
-+ }
-+ bh = ext3_append(handle, dir, &block, &retval);
- if (!bh)
- return retval;
-- rec_len = EXT3_DIR_REC_LEN(namelen);
-- offset = 0;
- de = (struct ext3_dir_entry_2 *) bh->b_data;
-- while (1) {
-- if ((char *)de >= sb->s_blocksize + bh->b_data) {
-- brelse (bh);
-- bh = NULL;
-- bh = ext3_bread (handle, dir,
-- offset >> EXT3_BLOCK_SIZE_BITS(sb), 1, &retval);
-- if (!bh)
-- return retval;
-- if (dir->i_size <= offset) {
-- if (dir->i_size == 0) {
-- brelse(bh);
-- return -ENOENT;
-- }
-+ de->inode = 0;
-+ de->rec_len = cpu_to_le16(rlen = blocksize);
-+ nlen = 0;
-+ return add_dirent_to_buf(handle, dentry, inode, de, bh);
-+}
-
-- ext3_debug ("creating next block\n");
-+#ifdef CONFIG_EXT3_INDEX
-+/*
-+ * Returns 0 for success, or a negative error value
-+ */
-+static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
-+ struct inode *inode)
-+{
-+ struct dx_frame frames[2], *frame;
-+ struct dx_entry *entries, *at;
-+ struct dx_hash_info hinfo;
-+ struct buffer_head * bh;
-+ struct inode *dir = dentry->d_parent->d_inode;
-+ struct super_block * sb = dir->i_sb;
-+ struct ext3_dir_entry_2 *de;
-+ int err;
-
-- BUFFER_TRACE(bh, "get_write_access");
-- ext3_journal_get_write_access(handle, bh);
-- de = (struct ext3_dir_entry_2 *) bh->b_data;
-- de->inode = 0;
-- de->rec_len = le16_to_cpu(sb->s_blocksize);
-- dir->u.ext3_i.i_disksize =
-- dir->i_size = offset + sb->s_blocksize;
-- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-- ext3_mark_inode_dirty(handle, dir);
-- } else {
-+ frame = dx_probe(dentry, 0, &hinfo, frames, &err);
-+ if (!frame)
-+ return err;
-+ entries = frame->entries;
-+ at = frame->at;
-
-- ext3_debug ("skipping to next block\n");
-+ if (!(bh = ext3_bread(handle,dir, dx_get_block(frame->at), 0, &err)))
-+ goto cleanup;
-
-- de = (struct ext3_dir_entry_2 *) bh->b_data;
-- }
-- }
-- if (!ext3_check_dir_entry ("ext3_add_entry", dir, de, bh,
-- offset)) {
-- brelse (bh);
-- return -ENOENT;
-- }
-- if (ext3_match (namelen, name, de)) {
-- brelse (bh);
-- return -EEXIST;
-+ BUFFER_TRACE(bh, "get_write_access");
-+ err = ext3_journal_get_write_access(handle, bh);
-+ if (err)
-+ goto journal_error;
-+
-+ err = add_dirent_to_buf(handle, dentry, inode, 0, bh);
-+ if (err != -ENOSPC) {
-+ bh = 0;
-+ goto cleanup;
-+ }
-+
-+ /* Block full, should compress but for now just split */
-+ dxtrace(printk("using %u of %u node entries\n",
-+ dx_get_count(entries), dx_get_limit(entries)));
-+ /* Need to split index? */
-+ if (dx_get_count(entries) == dx_get_limit(entries)) {
-+ u32 newblock;
-+ unsigned icount = dx_get_count(entries);
-+ int levels = frame - frames;
-+ struct dx_entry *entries2;
-+ struct dx_node *node2;
-+ struct buffer_head *bh2;
-+
-+ if (levels && (dx_get_count(frames->entries) ==
-+ dx_get_limit(frames->entries))) {
-+ ext3_warning(sb, __FUNCTION__,
-+ "Directory index full!\n");
-+ err = -ENOSPC;
-+ goto cleanup;
- }
-- if ((le32_to_cpu(de->inode) == 0 &&
-- le16_to_cpu(de->rec_len) >= rec_len) ||
-- (le16_to_cpu(de->rec_len) >=
-- EXT3_DIR_REC_LEN(de->name_len) + rec_len)) {
-- BUFFER_TRACE(bh, "get_write_access");
-- ext3_journal_get_write_access(handle, bh);
-- /* By now the buffer is marked for journaling */
-- offset += le16_to_cpu(de->rec_len);
-- if (le32_to_cpu(de->inode)) {
-- de1 = (struct ext3_dir_entry_2 *) ((char *) de +
-- EXT3_DIR_REC_LEN(de->name_len));
-- de1->rec_len =
-- cpu_to_le16(le16_to_cpu(de->rec_len) -
-- EXT3_DIR_REC_LEN(de->name_len));
-- de->rec_len = cpu_to_le16(
-- EXT3_DIR_REC_LEN(de->name_len));
-- de = de1;
-+ bh2 = ext3_append (handle, dir, &newblock, &err);
-+ if (!(bh2))
-+ goto cleanup;
-+ node2 = (struct dx_node *)(bh2->b_data);
-+ entries2 = node2->entries;
-+ node2->fake.rec_len = cpu_to_le16(sb->s_blocksize);
-+ node2->fake.inode = 0;
-+ BUFFER_TRACE(frame->bh, "get_write_access");
-+ err = ext3_journal_get_write_access(handle, frame->bh);
-+ if (err)
-+ goto journal_error;
-+ if (levels) {
-+ unsigned icount1 = icount/2, icount2 = icount - icount1;
-+ unsigned hash2 = dx_get_hash(entries + icount1);
-+ dxtrace(printk("Split index %i/%i\n", icount1, icount2));
-+
-+ BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */
-+ err = ext3_journal_get_write_access(handle,
-+ frames[0].bh);
-+ if (err)
-+ goto journal_error;
-+
-+ memcpy ((char *) entries2, (char *) (entries + icount1),
-+ icount2 * sizeof(struct dx_entry));
-+ dx_set_count (entries, icount1);
-+ dx_set_count (entries2, icount2);
-+ dx_set_limit (entries2, dx_node_limit(dir));
-+
-+ /* Which index block gets the new entry? */
-+ if (at - entries >= icount1) {
-+ frame->at = at = at - entries - icount1 + entries2;
-+ frame->entries = entries = entries2;
-+ swap(frame->bh, bh2);
- }
-- de->file_type = EXT3_FT_UNKNOWN;
-- if (inode) {
-- de->inode = cpu_to_le32(inode->i_ino);
-- ext3_set_de_type(dir->i_sb, de, inode->i_mode);
-- } else
-- de->inode = 0;
-- de->name_len = namelen;
-- memcpy (de->name, name, namelen);
-- /*
-- * XXX shouldn't update any times until successful
-- * completion of syscall, but too many callers depend
-- * on this.
-- *
-- * XXX similarly, too many callers depend on
-- * ext3_new_inode() setting the times, but error
-- * recovery deletes the inode, so the worst that can
-- * happen is that the times are slightly out of date
-- * and/or different from the directory change time.
-- */
-- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
-- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-- dir->i_version = ++event;
-- ext3_mark_inode_dirty(handle, dir);
-- BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
-- ext3_journal_dirty_metadata(handle, bh);
-- brelse(bh);
-- return 0;
-+ dx_insert_block (frames + 0, hash2, newblock);
-+ dxtrace(dx_show_index ("node", frames[1].entries));
-+ dxtrace(dx_show_index ("node",
-+ ((struct dx_node *) bh2->b_data)->entries));
-+ err = ext3_journal_dirty_metadata(handle, bh2);
-+ if (err)
-+ goto journal_error;
-+ brelse (bh2);
-+ } else {
-+ dxtrace(printk("Creating second level index...\n"));
-+ memcpy((char *) entries2, (char *) entries,
-+ icount * sizeof(struct dx_entry));
-+ dx_set_limit(entries2, dx_node_limit(dir));
-+
-+ /* Set up root */
-+ dx_set_count(entries, 1);
-+ dx_set_block(entries + 0, newblock);
-+ ((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels = 1;
-+
-+ /* Add new access path frame */
-+ frame = frames + 1;
-+ frame->at = at = at - entries + entries2;
-+ frame->entries = entries = entries2;
-+ frame->bh = bh2;
-+ err = ext3_journal_get_write_access(handle,
-+ frame->bh);
-+ if (err)
-+ goto journal_error;
- }
-- offset += le16_to_cpu(de->rec_len);
-- de = (struct ext3_dir_entry_2 *)
-- ((char *) de + le16_to_cpu(de->rec_len));
-+ ext3_journal_dirty_metadata(handle, frames[0].bh);
- }
-- brelse (bh);
-- return -ENOSPC;
-+ de = do_split(handle, dir, &bh, frame, &hinfo, &err);
-+ if (!de)
-+ goto cleanup;
-+ err = add_dirent_to_buf(handle, dentry, inode, de, bh);
-+ bh = 0;
-+ goto cleanup;
-+
-+journal_error:
-+ ext3_std_error(dir->i_sb, err);
-+cleanup:
-+ if (bh)
-+ brelse(bh);
-+ dx_release(frames);
-+ return err;
- }
-+#endif
-
- /*
- * ext3_delete_entry deletes a directory entry by merging it with the
-@@ -455,9 +1547,11 @@ static int ext3_create (struct inode * d
- struct inode * inode;
- int err;
-
-- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3);
-- if (IS_ERR(handle))
-+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
-+ if (IS_ERR(handle)) {
- return PTR_ERR(handle);
-+ }
-
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-@@ -481,9 +1575,11 @@ static int ext3_mknod (struct inode * di
- struct inode *inode;
- int err;
-
-- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3);
-- if (IS_ERR(handle))
-+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
-+ if (IS_ERR(handle)) {
- return PTR_ERR(handle);
-+ }
-
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-@@ -509,9 +1605,11 @@ static int ext3_mkdir(struct inode * dir
- if (dir->i_nlink >= EXT3_LINK_MAX)
- return -EMLINK;
-
-- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3);
-- if (IS_ERR(handle))
-+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
-+ if (IS_ERR(handle)) {
- return PTR_ERR(handle);
-+ }
-
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-@@ -523,7 +1621,7 @@ static int ext3_mkdir(struct inode * dir
-
- inode->i_op = &ext3_dir_inode_operations;
- inode->i_fop = &ext3_dir_operations;
-- inode->i_size = inode->u.ext3_i.i_disksize = inode->i_sb->s_blocksize;
-+ inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
- inode->i_blocks = 0;
- dir_block = ext3_bread (handle, inode, 0, 1, &err);
- if (!dir_block) {
-@@ -556,21 +1654,19 @@ static int ext3_mkdir(struct inode * dir
- inode->i_mode |= S_ISGID;
- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_entry (handle, dentry, inode);
-- if (err)
-- goto out_no_entry;
-+ if (err) {
-+ inode->i_nlink = 0;
-+ ext3_mark_inode_dirty(handle, inode);
-+ iput (inode);
-+ goto out_stop;
-+ }
- dir->i_nlink++;
-- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ ext3_update_dx_flag(dir);
- ext3_mark_inode_dirty(handle, dir);
- d_instantiate(dentry, inode);
- out_stop:
- ext3_journal_stop(handle, dir);
- return err;
--
--out_no_entry:
-- inode->i_nlink = 0;
-- ext3_mark_inode_dirty(handle, inode);
-- iput (inode);
-- goto out_stop;
- }
-
- /*
-@@ -657,7 +1753,7 @@ int ext3_orphan_add(handle_t *handle, st
- int err = 0, rc;
-
- lock_super(sb);
-- if (!list_empty(&inode->u.ext3_i.i_orphan))
-+ if (!list_empty(&EXT3_I(inode)->i_orphan))
- goto out_unlock;
-
- /* Orphan handling is only valid for files with data blocks
-@@ -698,7 +1794,7 @@ int ext3_orphan_add(handle_t *handle, st
- * This is safe: on error we're going to ignore the orphan list
- * anyway on the next recovery. */
- if (!err)
-- list_add(&inode->u.ext3_i.i_orphan, &EXT3_SB(sb)->s_orphan);
-+ list_add(&EXT3_I(inode)->i_orphan, &EXT3_SB(sb)->s_orphan);
-
- jbd_debug(4, "superblock will point to %ld\n", inode->i_ino);
- jbd_debug(4, "orphan inode %ld will point to %d\n",
-@@ -716,25 +1812,26 @@ out_unlock:
- int ext3_orphan_del(handle_t *handle, struct inode *inode)
- {
- struct list_head *prev;
-+ struct ext3_inode_info *ei = EXT3_I(inode);
- struct ext3_sb_info *sbi;
- unsigned long ino_next;
- struct ext3_iloc iloc;
- int err = 0;
-
- lock_super(inode->i_sb);
-- if (list_empty(&inode->u.ext3_i.i_orphan)) {
-+ if (list_empty(&ei->i_orphan)) {
- unlock_super(inode->i_sb);
- return 0;
- }
-
- ino_next = NEXT_ORPHAN(inode);
-- prev = inode->u.ext3_i.i_orphan.prev;
-+ prev = ei->i_orphan.prev;
- sbi = EXT3_SB(inode->i_sb);
-
- jbd_debug(4, "remove inode %lu from orphan list\n", inode->i_ino);
-
-- list_del(&inode->u.ext3_i.i_orphan);
-- INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
-+ list_del(&ei->i_orphan);
-+ INIT_LIST_HEAD(&ei->i_orphan);
-
- /* If we're on an error path, we may not have a valid
- * transaction handle with which to update the orphan list on
-@@ -795,8 +1892,9 @@ static int ext3_rmdir (struct inode * di
- handle_t *handle;
-
- handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
-- if (IS_ERR(handle))
-+ if (IS_ERR(handle)) {
- return PTR_ERR(handle);
-+ }
-
- retval = -ENOENT;
- bh = ext3_find_entry (dentry, &de);
-@@ -834,7 +1932,7 @@ static int ext3_rmdir (struct inode * di
- dir->i_nlink--;
- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
- ext3_mark_inode_dirty(handle, inode);
-- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ ext3_update_dx_flag(dir);
- ext3_mark_inode_dirty(handle, dir);
-
- end_rmdir:
-@@ -852,8 +1950,9 @@ static int ext3_unlink(struct inode * di
- handle_t *handle;
-
- handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
-- if (IS_ERR(handle))
-+ if (IS_ERR(handle)) {
- return PTR_ERR(handle);
-+ }
-
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-@@ -880,7 +1979,7 @@ static int ext3_unlink(struct inode * di
- if (retval)
- goto end_unlink;
- dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ ext3_update_dx_flag(dir);
- ext3_mark_inode_dirty(handle, dir);
- inode->i_nlink--;
- if (!inode->i_nlink)
-@@ -906,9 +2005,11 @@ static int ext3_symlink (struct inode *
- if (l > dir->i_sb->s_blocksize)
- return -ENAMETOOLONG;
-
-- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 5);
-- if (IS_ERR(handle))
-+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5);
-+ if (IS_ERR(handle)) {
- return PTR_ERR(handle);
-+ }
-
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-@@ -918,7 +2019,7 @@ static int ext3_symlink (struct inode *
- if (IS_ERR(inode))
- goto out_stop;
-
-- if (l > sizeof (inode->u.ext3_i.i_data)) {
-+ if (l > sizeof (EXT3_I(inode)->i_data)) {
- inode->i_op = &page_symlink_inode_operations;
- inode->i_mapping->a_ops = &ext3_aops;
- /*
-@@ -927,24 +2028,22 @@ static int ext3_symlink (struct inode *
- * i_size in generic_commit_write().
- */
- err = block_symlink(inode, symname, l);
-- if (err)
-- goto out_no_entry;
-+ if (err) {
-+ ext3_dec_count(handle, inode);
-+ ext3_mark_inode_dirty(handle, inode);
-+ iput (inode);
-+ goto out_stop;
-+ }
- } else {
- inode->i_op = &ext3_fast_symlink_inode_operations;
-- memcpy((char*)&inode->u.ext3_i.i_data,symname,l);
-+ memcpy((char*)&EXT3_I(inode)->i_data,symname,l);
- inode->i_size = l-1;
- }
-- inode->u.ext3_i.i_disksize = inode->i_size;
-+ EXT3_I(inode)->i_disksize = inode->i_size;
- err = ext3_add_nondir(handle, dentry, inode);
- out_stop:
- ext3_journal_stop(handle, dir);
- return err;
--
--out_no_entry:
-- ext3_dec_count(handle, inode);
-- ext3_mark_inode_dirty(handle, inode);
-- iput (inode);
-- goto out_stop;
- }
-
- static int ext3_link (struct dentry * old_dentry,
-@@ -957,12 +2056,15 @@ static int ext3_link (struct dentry * ol
- if (S_ISDIR(inode->i_mode))
- return -EPERM;
-
-- if (inode->i_nlink >= EXT3_LINK_MAX)
-+ if (inode->i_nlink >= EXT3_LINK_MAX) {
- return -EMLINK;
-+ }
-
-- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS);
-- if (IS_ERR(handle))
-+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS);
-+ if (IS_ERR(handle)) {
- return PTR_ERR(handle);
-+ }
-
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-@@ -995,9 +2097,11 @@ static int ext3_rename (struct inode * o
-
- old_bh = new_bh = dir_bh = NULL;
-
-- handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + 2);
-- if (IS_ERR(handle))
-+ handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2);
-+ if (IS_ERR(handle)) {
- return PTR_ERR(handle);
-+ }
-
- if (IS_SYNC(old_dir) || IS_SYNC(new_dir))
- handle->h_sync = 1;
-@@ -1070,14 +2174,37 @@ static int ext3_rename (struct inode * o
- /*
- * ok, that's it
- */
-- ext3_delete_entry(handle, old_dir, old_de, old_bh);
-+ if (le32_to_cpu(old_de->inode) != old_inode->i_ino ||
-+ old_de->name_len != old_dentry->d_name.len ||
-+ strncmp(old_de->name, old_dentry->d_name.name, old_de->name_len) ||
-+ (retval = ext3_delete_entry(handle, old_dir,
-+ old_de, old_bh)) == -ENOENT) {
-+ /* old_de could have moved from under us during htree split, so
-+ * make sure that we are deleting the right entry. We might
-+ * also be pointing to a stale entry in the unused part of
-+ * old_bh so just checking inum and the name isn't enough. */
-+ struct buffer_head *old_bh2;
-+ struct ext3_dir_entry_2 *old_de2;
-+
-+ old_bh2 = ext3_find_entry(old_dentry, &old_de2);
-+ if (old_bh2) {
-+ retval = ext3_delete_entry(handle, old_dir,
-+ old_de2, old_bh2);
-+ brelse(old_bh2);
-+ }
-+ }
-+ if (retval) {
-+ ext3_warning(old_dir->i_sb, "ext3_rename",
-+ "Deleting old file (%lu), %d, error=%d",
-+ old_dir->i_ino, old_dir->i_nlink, retval);
-+ }
-
- if (new_inode) {
- new_inode->i_nlink--;
- new_inode->i_ctime = CURRENT_TIME;
- }
- old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
-- old_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ ext3_update_dx_flag(old_dir);
- if (dir_bh) {
- BUFFER_TRACE(dir_bh, "get_write_access");
- ext3_journal_get_write_access(handle, dir_bh);
-@@ -1089,7 +2212,7 @@ static int ext3_rename (struct inode * o
- new_inode->i_nlink--;
- } else {
- new_dir->i_nlink++;
-- new_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ ext3_update_dx_flag(new_dir);
- ext3_mark_inode_dirty(handle, new_dir);
- }
- }
---- linux-2.4.22-ac1/fs/ext3/super.c~ext3-htree-2.4.22-rh 2003-09-25 14:39:01.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext3/super.c 2003-09-25 14:55:12.000000000 +0400
-@@ -714,6 +714,7 @@ static int ext3_setup_super(struct super
- es->s_mtime = cpu_to_le32(CURRENT_TIME);
- ext3_update_dynamic_rev(sb);
- EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
-+
- ext3_commit_super (sb, es, 1);
- if (test_opt (sb, DEBUG))
- printk (KERN_INFO
-@@ -724,6 +725,7 @@ static int ext3_setup_super(struct super
- EXT3_BLOCKS_PER_GROUP(sb),
- EXT3_INODES_PER_GROUP(sb),
- sbi->s_mount_opt);
-+
- printk(KERN_INFO "EXT3 FS " EXT3FS_VERSION ", " EXT3FS_DATE " on %s, ",
- bdevname(sb->s_dev));
- if (EXT3_SB(sb)->s_journal->j_inode == NULL) {
-@@ -897,6 +899,7 @@ static loff_t ext3_max_size(int bits)
- return res;
- }
-
-+
- struct super_block * ext3_read_super (struct super_block * sb, void * data,
- int silent)
- {
-@@ -1073,6 +1076,9 @@ struct super_block * ext3_read_super (st
- sbi->s_mount_state = le16_to_cpu(es->s_state);
- sbi->s_addr_per_block_bits = log2(EXT3_ADDR_PER_BLOCK(sb));
- sbi->s_desc_per_block_bits = log2(EXT3_DESC_PER_BLOCK(sb));
-+ for (i=0; i < 4; i++)
-+ sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
-+ sbi->s_def_hash_version = es->s_def_hash_version;
-
- if (sbi->s_blocks_per_group > blocksize * 8) {
- printk (KERN_ERR
-@@ -1846,6 +1852,7 @@ static void __exit exit_ext3_fs(void)
- unregister_filesystem(&ext3_fs_type);
- }
-
-+EXPORT_SYMBOL(ext3_force_commit);
- EXPORT_SYMBOL(ext3_bread);
-
- MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
---- linux-2.4.22-ac1/include/linux/ext3_fs.h~ext3-htree-2.4.22-rh 2003-09-25 14:16:29.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/include/linux/ext3_fs.h 2003-09-25 14:58:30.000000000 +0400
-@@ -40,6 +40,11 @@
- #define EXT3FS_VERSION "2.4-0.9.19"
-
- /*
-+ * Always enable hashed directories
-+ */
-+#define CONFIG_EXT3_INDEX
-+
-+/*
- * Debug code
- */
- #ifdef EXT3FS_DEBUG
-@@ -440,8 +445,11 @@ struct ext3_super_block {
- /*E0*/ __u32 s_journal_inum; /* inode number of journal file */
- __u32 s_journal_dev; /* device number of journal file */
- __u32 s_last_orphan; /* start of list of inodes to delete */
--
--/*EC*/ __u32 s_reserved[197]; /* Padding to the end of the block */
-+ __u32 s_hash_seed[4]; /* HTREE hash seed */
-+ __u8 s_def_hash_version; /* Default hash version to use */
-+ __u8 s_reserved_char_pad;
-+ __u16 s_reserved_word_pad;
-+ __u32 s_reserved[192]; /* Padding to the end of the block */
- };
-
- #ifdef __KERNEL__
-@@ -578,9 +586,46 @@ struct ext3_dir_entry_2 {
- #define EXT3_DIR_ROUND (EXT3_DIR_PAD - 1)
- #define EXT3_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT3_DIR_ROUND) & \
- ~EXT3_DIR_ROUND)
-+/*
-+ * Hash Tree Directory indexing
-+ * (c) Daniel Phillips, 2001
-+ */
-+
-+#ifdef CONFIG_EXT3_INDEX
-+ #define is_dx(dir) (EXT3_HAS_COMPAT_FEATURE(dir->i_sb, \
-+ EXT3_FEATURE_COMPAT_DIR_INDEX) && \
-+ (EXT3_I(dir)->i_flags & EXT3_INDEX_FL))
-+#define EXT3_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT3_LINK_MAX)
-+#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1)
-+#else
-+ #define is_dx(dir) 0
-+#define EXT3_DIR_LINK_MAX(dir) ((dir)->i_nlink >= EXT3_LINK_MAX)
-+#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2)
-+#endif
-+
-+/* Legal values for the dx_root hash_version field: */
-+
-+#define DX_HASH_LEGACY 0
-+#define DX_HASH_HALF_MD4 1
-+#define DX_HASH_TEA 2
-+
-+/* hash info structure used by the directory hash */
-+struct dx_hash_info
-+{
-+ u32 hash;
-+ u32 minor_hash;
-+ int hash_version;
-+ u32 *seed;
-+};
-
- #ifdef __KERNEL__
- /*
-+ * Control parameters used by ext3_htree_next_block
-+ */
-+#define HASH_NB_ALWAYS 1
-+
-+
-+/*
- * Describe an inode's exact location on disk and in memory
- */
- struct ext3_iloc
-@@ -590,6 +635,27 @@ struct ext3_iloc
- unsigned long block_group;
- };
-
-+
-+/*
-+ * This structure is stuffed into the struct file's private_data field
-+ * for directories. It is where we put information so that we can do
-+ * readdir operations in hash tree order.
-+ */
-+struct dir_private_info {
-+ rb_root_t root;
-+ rb_node_t *curr_node;
-+ struct fname *extra_fname;
-+ loff_t last_pos;
-+ __u32 curr_hash;
-+ __u32 curr_minor_hash;
-+ __u32 next_hash;
-+};
-+
-+/*
-+ * Special error return code only used by dx_probe() and its callers.
-+ */
-+#define ERR_BAD_DX_DIR -75000
-+
- /*
- * Function prototypes
- */
-@@ -617,11 +683,20 @@ extern struct ext3_group_desc * ext3_get
-
- /* dir.c */
- extern int ext3_check_dir_entry(const char *, struct inode *,
-- struct ext3_dir_entry_2 *, struct buffer_head *,
-- unsigned long);
-+ struct ext3_dir_entry_2 *,
-+ struct buffer_head *, unsigned long);
-+extern int ext3_htree_store_dirent(struct file *dir_file, __u32 hash,
-+ __u32 minor_hash,
-+ struct ext3_dir_entry_2 *dirent);
-+extern void ext3_htree_free_dir_info(struct dir_private_info *p);
-+
- /* fsync.c */
- extern int ext3_sync_file (struct file *, struct dentry *, int);
-
-+/* hash.c */
-+extern int ext3fs_dirhash(const char *name, int len, struct
-+ dx_hash_info *hinfo);
-+
- /* ialloc.c */
- extern struct inode * ext3_new_inode (handle_t *, const struct inode *, int);
- extern void ext3_free_inode (handle_t *, struct inode *);
-@@ -655,6 +730,8 @@ extern int ext3_ioctl (struct inode *, s
- /* namei.c */
- extern int ext3_orphan_add(handle_t *, struct inode *);
- extern int ext3_orphan_del(handle_t *, struct inode *);
-+extern int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash,
-+ __u32 start_minor_hash, __u32 *next_hash);
-
- /* super.c */
- extern void ext3_error (struct super_block *, const char *, const char *, ...)
---- linux-2.4.22-ac1/include/linux/ext3_fs_sb.h~ext3-htree-2.4.22-rh 2003-09-25 14:16:34.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/include/linux/ext3_fs_sb.h 2003-09-25 14:55:12.000000000 +0400
-@@ -62,6 +62,8 @@ struct ext3_sb_info {
- int s_inode_size;
- int s_first_ino;
- u32 s_next_generation;
-+ u32 s_hash_seed[4];
-+ int s_def_hash_version;
-
- unsigned long s_dir_count;
- u8 *s_debts;
---- linux-2.4.22-ac1/include/linux/ext3_jbd.h~ext3-htree-2.4.22-rh 2003-06-13 18:51:38.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/include/linux/ext3_jbd.h 2003-09-25 14:55:12.000000000 +0400
-@@ -63,6 +63,8 @@ extern int ext3_writepage_trans_blocks(s
-
- #define EXT3_RESERVE_TRANS_BLOCKS 12U
-
-+#define EXT3_INDEX_EXTRA_TRANS_BLOCKS 8
-+
- int
- ext3_mark_iloc_dirty(handle_t *handle,
- struct inode *inode,
---- linux-2.4.22-ac1/include/linux/rbtree.h~ext3-htree-2.4.22-rh 2001-11-22 22:46:18.000000000 +0300
-+++ linux-2.4.22-ac1-alexey/include/linux/rbtree.h 2003-09-25 14:55:12.000000000 +0400
-@@ -120,6 +120,8 @@ rb_root_t;
-
- extern void rb_insert_color(rb_node_t *, rb_root_t *);
- extern void rb_erase(rb_node_t *, rb_root_t *);
-+extern rb_node_t *rb_get_first(rb_root_t *root);
-+extern rb_node_t *rb_get_next(rb_node_t *n);
-
- static inline void rb_link_node(rb_node_t * node, rb_node_t * parent, rb_node_t ** rb_link)
- {
---- linux-2.4.22-ac1/lib/rbtree.c~ext3-htree-2.4.22-rh 2002-08-03 04:39:46.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/lib/rbtree.c 2003-09-25 14:55:12.000000000 +0400
-@@ -17,6 +17,8 @@
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- linux/lib/rbtree.c
-+
-+ rb_get_first and rb_get_next written by Theodore Ts'o, 9/8/2002
- */
-
- #include <linux/rbtree.h>
-@@ -294,3 +296,43 @@ void rb_erase(rb_node_t * node, rb_root_
- __rb_erase_color(child, parent, root);
- }
- EXPORT_SYMBOL(rb_erase);
-+
-+/*
-+ * This function returns the first node (in sort order) of the tree.
-+ */
-+rb_node_t *rb_get_first(rb_root_t *root)
-+{
-+ rb_node_t *n;
-+
-+ n = root->rb_node;
-+ if (!n)
-+ return 0;
-+ while (n->rb_left)
-+ n = n->rb_left;
-+ return n;
-+}
-+EXPORT_SYMBOL(rb_get_first);
-+
-+/*
-+ * Given a node, this function will return the next node in the tree.
-+ */
-+rb_node_t *rb_get_next(rb_node_t *n)
-+{
-+ rb_node_t *parent;
-+
-+ if (n->rb_right) {
-+ n = n->rb_right;
-+ while (n->rb_left)
-+ n = n->rb_left;
-+ return n;
-+ } else {
-+ while ((parent = n->rb_parent)) {
-+ if (n == parent->rb_left)
-+ return parent;
-+ n = parent;
-+ }
-+ return 0;
-+ }
-+}
-+EXPORT_SYMBOL(rb_get_next);
-+
-
-_
+++ /dev/null
-Index: linux-2.4.20/fs/ext3/ialloc.c
-===================================================================
---- linux-2.4.20.orig/fs/ext3/ialloc.c 2003-10-25 00:37:13.000000000 +0400
-+++ linux-2.4.20/fs/ext3/ialloc.c 2003-10-29 20:33:33.000000000 +0300
-@@ -241,11 +241,16 @@
-
- bh = sb->u.ext3_sb.s_inode_bitmap[bitmap_nr];
-
-- BUFFER_TRACE(bh, "get_write_access");
-- fatal = ext3_journal_get_write_access(handle, bh);
-+ BUFFER_TRACE(bh, "get_undo_access");
-+ fatal = ext3_journal_get_undo_access(handle, bh);
- if (fatal)
- goto error_return;
-
-+ /* to prevent inode reusing within single transaction -bzzz */
-+ BUFFER_TRACE(bh, "clear in b_committed_data");
-+ J_ASSERT_BH(bh, bh2jh(bh)->b_committed_data != NULL);
-+ ext3_set_bit(bit, bh2jh(bh)->b_committed_data);
-+
- /* Ok, now we can actually update the inode bitmaps.. */
- if (!ext3_clear_bit (bit, bh->b_data))
- ext3_error (sb, "ext3_free_inode",
-@@ -319,6 +324,131 @@
- return 0;
- }
-
-+static int ext3_test_allocatable(int nr, struct buffer_head *bh)
-+{
-+ if (ext3_test_bit(nr, bh->b_data))
-+ return 0;
-+ if (!buffer_jbd(bh) || !bh2jh(bh)->b_committed_data)
-+ return 1;
-+#if 0
-+ if (!ext3_test_bit(nr, bh2jh(bh)->b_committed_data))
-+ printk("EXT3-fs: inode %d was used\n", nr);
-+#endif
-+ return !ext3_test_bit(nr, bh2jh(bh)->b_committed_data);
-+}
-+
-+int ext3_find_group_dir(const struct inode *dir,
-+ struct ext3_group_desc **gdp,
-+ struct buffer_head **bh)
-+{
-+ struct super_block *sb = dir->i_sb;
-+ struct ext3_super_block *es;
-+ struct ext3_group_desc *tmp;
-+ int i = 0, j, avefreei;
-+
-+ es = EXT3_SB(sb)->s_es;
-+ avefreei = le32_to_cpu(es->s_free_inodes_count) /
-+ sb->u.ext3_sb.s_groups_count;
-+ for (j = 0; j < sb->u.ext3_sb.s_groups_count; j++) {
-+ struct buffer_head *temp_buffer;
-+ tmp = ext3_get_group_desc(sb, j, &temp_buffer);
-+ if (tmp && le16_to_cpu(tmp->bg_free_inodes_count) &&
-+ le16_to_cpu(tmp->bg_free_inodes_count) >= avefreei) {
-+ if (!*gdp || (le16_to_cpu(tmp->bg_free_blocks_count) >
-+ le16_to_cpu((*gdp)->bg_free_blocks_count))) {
-+ i = j;
-+ *gdp = tmp;
-+ *bh = temp_buffer;
-+ }
-+ }
-+ }
-+
-+ return i;
-+}
-+
-+int ext3_find_group_other(const struct inode *dir,
-+ struct ext3_group_desc **gdp,
-+ struct buffer_head **bh)
-+{
-+ struct super_block *sb = dir->i_sb;
-+ struct ext3_group_desc *tmp;
-+ int i, j;
-+
-+ /*
-+ * Try to place the inode in its parent directory
-+ */
-+ i = dir->u.ext3_i.i_block_group;
-+ tmp = ext3_get_group_desc(sb, i, bh);
-+ if (tmp && le16_to_cpu(tmp->bg_free_inodes_count))
-+ *gdp = tmp;
-+ else {
-+ /*
-+ * Use a quadratic hash to find a group with a
-+ * free inode
-+ */
-+ for (j = 1; j < sb->u.ext3_sb.s_groups_count; j <<= 1) {
-+ i += j;
-+ if (i >= sb->u.ext3_sb.s_groups_count)
-+ i -= sb->u.ext3_sb.s_groups_count;
-+ tmp = ext3_get_group_desc (sb, i, bh);
-+ if (tmp && le16_to_cpu(tmp->bg_free_inodes_count)) {
-+ *gdp = tmp;
-+ break;
-+ }
-+ }
-+ }
-+ if (!*gdp) {
-+ /*
-+ * That failed: try linear search for a free inode
-+ */
-+ i = dir->u.ext3_i.i_block_group + 1;
-+ for (j = 2; j < sb->u.ext3_sb.s_groups_count; j++) {
-+ if (++i >= sb->u.ext3_sb.s_groups_count)
-+ i = 0;
-+ tmp = ext3_get_group_desc (sb, i, bh);
-+ if (tmp && le16_to_cpu(tmp->bg_free_inodes_count)) {
-+ *gdp = tmp;
-+ break;
-+ }
-+ }
-+ }
-+
-+ return i;
-+}
-+
-+static int ext3_find_group(const struct inode *dir, int mode,
-+ struct ext3_group_desc **gdp,
-+ struct buffer_head **bh)
-+{
-+ if (S_ISDIR(mode))
-+ return ext3_find_group_dir(dir, gdp, bh);
-+ return ext3_find_group_other(dir, gdp, bh);
-+}
-+
-+static int ext3_find_usable_inode(struct super_block *sb,
-+ struct buffer_head *bh)
-+{
-+ int here, maxinodes, next;
-+
-+ maxinodes = EXT3_INODES_PER_GROUP(sb);
-+ here = 0;
-+
-+ while (here < maxinodes) {
-+ next = ext3_find_next_zero_bit((unsigned long *) bh->b_data,
-+ maxinodes, here);
-+ if (next >= maxinodes)
-+ return -1;
-+ if (ext3_test_allocatable(next, bh))
-+ return next;
-+
-+ J_ASSERT_BH(bh, bh2jh(bh)->b_committed_data);
-+ here = ext3_find_next_zero_bit
-+ ((unsigned long *) bh2jh(bh)->b_committed_data,
-+ maxinodes, next);
-+ }
-+ return -1;
-+}
-+
- /*
- * There are two policies for allocating an inode. If the new inode is
- * a directory, then a forward search is made for a block group with both
-@@ -336,7 +466,7 @@
- struct super_block * sb;
- struct buffer_head * bh;
- struct buffer_head * bh2;
-- int i, j, avefreei;
-+ int i, j, k;
- struct inode * inode;
- int bitmap_nr;
- struct ext3_group_desc * gdp;
-@@ -371,11 +501,12 @@
-
- bh = EXT3_SB(sb)->s_inode_bitmap[bitmap_nr];
-
-- BUFFER_TRACE(bh, "get_write_access");
-- err = ext3_journal_get_write_access(handle, bh);
-+ BUFFER_TRACE(bh, "get_undo_access");
-+ err = ext3_journal_get_undo_access(handle, bh);
- if (err) goto fail;
-
-- if (ext3_set_bit(j, bh->b_data)) {
-+ if (!ext3_test_allocatable(j, bh) ||
-+ ext3_set_bit(j, bh->b_data)) {
- printk(KERN_ERR "goal inode %lu unavailable\n", goal);
- /* Oh well, we tried. */
- goto repeat;
-@@ -393,119 +524,70 @@
-
- repeat:
- gdp = NULL;
-- i = 0;
--
-- if (S_ISDIR(mode)) {
-- avefreei = le32_to_cpu(es->s_free_inodes_count) /
-- sb->u.ext3_sb.s_groups_count;
-- if (!gdp) {
-- for (j = 0; j < sb->u.ext3_sb.s_groups_count; j++) {
-- struct buffer_head *temp_buffer;
-- tmp = ext3_get_group_desc (sb, j, &temp_buffer);
-- if (tmp &&
-- le16_to_cpu(tmp->bg_free_inodes_count) &&
-- le16_to_cpu(tmp->bg_free_inodes_count) >=
-- avefreei) {
-- if (!gdp || (le16_to_cpu(tmp->bg_free_blocks_count) >
-- le16_to_cpu(gdp->bg_free_blocks_count))) {
-- i = j;
-- gdp = tmp;
-- bh2 = temp_buffer;
-- }
-- }
-- }
-- }
-- } else {
-- /*
-- * Try to place the inode in its parent directory
-- */
-- i = dir->u.ext3_i.i_block_group;
-- tmp = ext3_get_group_desc (sb, i, &bh2);
-- if (tmp && le16_to_cpu(tmp->bg_free_inodes_count))
-- gdp = tmp;
-- else
-- {
-- /*
-- * Use a quadratic hash to find a group with a
-- * free inode
-- */
-- for (j = 1; j < sb->u.ext3_sb.s_groups_count; j <<= 1) {
-- i += j;
-- if (i >= sb->u.ext3_sb.s_groups_count)
-- i -= sb->u.ext3_sb.s_groups_count;
-- tmp = ext3_get_group_desc (sb, i, &bh2);
-- if (tmp &&
-- le16_to_cpu(tmp->bg_free_inodes_count)) {
-- gdp = tmp;
-- break;
-- }
-- }
-- }
-- if (!gdp) {
-- /*
-- * That failed: try linear search for a free inode
-- */
-- i = dir->u.ext3_i.i_block_group + 1;
-- for (j = 2; j < sb->u.ext3_sb.s_groups_count; j++) {
-- if (++i >= sb->u.ext3_sb.s_groups_count)
-- i = 0;
-- tmp = ext3_get_group_desc (sb, i, &bh2);
-- if (tmp &&
-- le16_to_cpu(tmp->bg_free_inodes_count)) {
-- gdp = tmp;
-- break;
-- }
-- }
-- }
-- }
-
-+ /* choose group */
-+ i = ext3_find_group(dir, mode, &gdp, &bh2);
- err = -ENOSPC;
- if (!gdp)
- goto out;
--
-+
- err = -EIO;
-- bitmap_nr = load_inode_bitmap (sb, i);
-+ bitmap_nr = load_inode_bitmap(sb, i);
- if (bitmap_nr < 0)
- goto fail;
--
- bh = sb->u.ext3_sb.s_inode_bitmap[bitmap_nr];
-
-- if ((j = ext3_find_first_zero_bit ((unsigned long *) bh->b_data,
-- EXT3_INODES_PER_GROUP(sb))) <
-- EXT3_INODES_PER_GROUP(sb)) {
-- BUFFER_TRACE(bh, "get_write_access");
-- err = ext3_journal_get_write_access(handle, bh);
-- if (err) goto fail;
--
-- if (ext3_set_bit (j, bh->b_data)) {
-- ext3_error (sb, "ext3_new_inode",
-- "bit already set for inode %d", j);
-- goto repeat;
-- }
-- BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
-- err = ext3_journal_dirty_metadata(handle, bh);
-- if (err) goto fail;
-- } else {
-- if (le16_to_cpu(gdp->bg_free_inodes_count) != 0) {
-- ext3_error (sb, "ext3_new_inode",
-- "Free inodes count corrupted in group %d",
-- i);
-- /* Is it really ENOSPC? */
-- err = -ENOSPC;
-- if (sb->s_flags & MS_RDONLY)
-- goto fail;
--
-- BUFFER_TRACE(bh2, "get_write_access");
-- err = ext3_journal_get_write_access(handle, bh2);
-- if (err) goto fail;
-- gdp->bg_free_inodes_count = 0;
-- BUFFER_TRACE(bh2, "call ext3_journal_dirty_metadata");
-- err = ext3_journal_dirty_metadata(handle, bh2);
-- if (err) goto fail;
-+ /* try to allocate in selected group */
-+ j = ext3_find_usable_inode(sb, bh);
-+ err = -ENOSPC;
-+ if (j >= 0)
-+ goto found_free;
-+
-+ /* can't allocate: try to allocate in ANY another groups */
-+ k = i;
-+ err = -EIO;
-+ for (i = i + 1; i != k; i++) {
-+ if (i >= sb->u.ext3_sb.s_groups_count)
-+ i = 0;
-+ tmp = ext3_get_group_desc(sb, i, &bh2);
-+ if (le16_to_cpu(tmp->bg_free_inodes_count) == 0)
-+ continue;
-+
-+ bitmap_nr = load_inode_bitmap(sb, i);
-+ if (bitmap_nr < 0)
-+ goto fail;
-+ bh = sb->u.ext3_sb.s_inode_bitmap[bitmap_nr];
-+
-+ /* try to allocate in selected group */
-+ if ((j = ext3_find_usable_inode(sb, bh)) >= 0) {
-+ gdp = tmp;
-+ break;
- }
-- goto repeat;
- }
-+ err = -ENOSPC;
-+ if (!gdp)
-+ goto out;
-+
-+ found_free:
-+ BUFFER_TRACE(bh, "get_undo_access");
-+ err = ext3_journal_get_undo_access(handle, bh);
-+ if (err)
-+ goto fail;
-+
-+ if (ext3_set_bit(j, bh->b_data)) {
-+ ext3_error (sb, "ext3_new_inode",
-+ "bit already set for inode %d", j);
-+ goto fail;
-+ }
-+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
-+ err = ext3_journal_dirty_metadata(handle, bh);
-+ if (err)
-+ goto fail;
-+
- have_bit_and_group:
-+ if (buffer_jbd(bh) && bh2jh(bh)->b_committed_data)
-+ J_ASSERT_BH(bh, !ext3_test_bit(j, bh2jh(bh)->b_committed_data));
-+
- j += i * EXT3_INODES_PER_GROUP(sb) + 1;
- if (j < EXT3_FIRST_INO(sb) || j > le32_to_cpu(es->s_inodes_count)) {
- ext3_error (sb, "ext3_new_inode",
+++ /dev/null
-
-
-
- fs/ext3/ext3-exports.c | 3 ++
- fs/ext3/inode.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++
- 2 files changed, 58 insertions(+)
-
-Index: lum/fs/ext3/inode.c
-===================================================================
---- lum.orig/fs/ext3/inode.c Sat Nov 22 16:38:51 2003
-+++ lum/fs/ext3/inode.c Fri Nov 28 00:37:18 2003
-@@ -2979,3 +2979,75 @@
- ret = ret2;
- return ret;
- }
-+
-+/* copied from fs/buffer.c */
-+static void unmap_underlying_metadata(struct buffer_head * bh)
-+{
-+ struct buffer_head *old_bh;
-+
-+ old_bh = get_hash_table(bh->b_dev, bh->b_blocknr, bh->b_size);
-+ if (old_bh) {
-+ mark_buffer_clean(old_bh);
-+ wait_on_buffer(old_bh);
-+ clear_bit(BH_Req, &old_bh->b_state);
-+ __brelse(old_bh);
-+ }
-+}
-+
-+int ext3_map_inode_page(struct inode *inode, struct page *page,
-+ unsigned long *blocks, int *created, int create)
-+{
-+ unsigned int blocksize, blocks_per_page;
-+ unsigned long iblock;
-+ void *handle;
-+ int i, rc = 0, failed = 0, needed_blocks;
-+
-+ blocksize = inode->i_sb->s_blocksize;
-+ blocks_per_page = PAGE_SIZE >> inode->i_sb->s_blocksize_bits;
-+ iblock = page->index * blocks_per_page;
-+
-+ for (i = 0; i < blocks_per_page; i++, iblock++) {
-+ blocks[i] = ext3_bmap(inode->i_mapping, iblock);
-+ if (blocks[i] == 0) {
-+ failed++;
-+ created[i] = -1;
-+ } else {
-+ created[i] = 0;
-+ }
-+ }
-+
-+ if (failed == 0 || create == 0)
-+ return 0;
-+
-+ needed_blocks = ext3_writepage_trans_blocks(inode);
-+ lock_kernel();
-+ handle = ext3_journal_start(inode, needed_blocks);
-+ unlock_kernel();
-+ if (IS_ERR(handle))
-+ return PTR_ERR(handle);
-+
-+ iblock = page->index * blocks_per_page;
-+ for (i = 0; i < blocks_per_page; i++, iblock++) {
-+ struct buffer_head bh;
-+
-+ if (blocks[i] != 0)
-+ continue;
-+
-+ rc = ext3_get_block_handle(handle, inode, iblock, &bh, 1);
-+ if (rc) {
-+ printk(KERN_INFO "ext3_map_inode_page: error %d "
-+ "allocating block %ld\n", rc, iblock);
-+ goto out;
-+ }
-+ if (buffer_new(&bh))
-+ unmap_underlying_metadata(&bh);
-+ blocks[i] = bh.b_blocknr;
-+ created[i] = 1;
-+ }
-+
-+ out:
-+ lock_kernel();
-+ ext3_journal_stop(handle, inode);
-+ unlock_kernel();
-+ return rc;
-+}
-Index: lum/fs/ext3/ext3-exports.c
-===================================================================
---- lum.orig/fs/ext3/ext3-exports.c Sat Nov 22 16:38:51 2003
-+++ lum/fs/ext3/ext3-exports.c Sat Nov 22 16:38:51 2003
-@@ -9,6 +9,8 @@
-
- int ext3_prep_san_write(struct inode *inode, long *blocks,
- int nblocks, loff_t newsize);
-+int ext3_map_inode_page(struct inode *inode, struct page *page,
-+ unsigned long *block, int *created, int create);
-
- EXPORT_SYMBOL(ext3_force_commit);
- EXPORT_SYMBOL(ext3_bread);
-@@ -18,3 +20,4 @@
- EXPORT_SYMBOL(ext3_xattr_list);
- EXPORT_SYMBOL(ext3_xattr_set);
- EXPORT_SYMBOL(ext3_prep_san_write);
-+EXPORT_SYMBOL(ext3_map_inode_page);
+++ /dev/null
-Index: linux-2.4.24/fs/ext3/balloc.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/balloc.c 2004-01-10 17:04:42.000000000 +0300
-+++ linux-2.4.24/fs/ext3/balloc.c 2004-02-06 11:05:42.000000000 +0300
-@@ -11,6 +11,7 @@
- * David S. Miller (davem@caip.rutgers.edu), 1995
- */
-
-+#include <linux/module.h>
- #include <linux/config.h>
- #include <linux/sched.h>
- #include <linux/fs.h>
-@@ -1007,3 +1008,303 @@
- bitmap_count);
- }
- #endif
-+
-+#define MBDEBUG_
-+#ifdef MBDEBUG
-+#define mbdebug(fmt,a...) printk(fmt, ##a)
-+#else
-+#define mbdebug(fmt,a...)
-+#endif
-+
-+/*
-+ * in alloc_status we track allocation: the best found extent, how many
-+ * extents we've skipped, etc
-+ */
-+struct alloc_status {
-+ struct inode *inode;
-+ struct super_block *sb;
-+ int goal; /* goal for allocation */
-+ int target_len; /* goal for len */
-+ int start, len; /* the best found extent */
-+ int num; /* number of extent: to limit searching */
-+};
-+
-+/*
-+ * ext3_test_extent() compares requested extent with existing in as.
-+ * if requested extent is better than that, then replace old one.
-+ * then it tries to understand is new extent suitable or not
-+ * return 1 if caller can complete searching
-+ */
-+inline int ext3_test_extent(struct alloc_status *as, int group,
-+ int start, int len)
-+{
-+ struct ext3_super_block * es = EXT3_SB(as->sb)->s_es;
-+ unsigned long tmp;
-+
-+ J_ASSERT(as->target_len >= len);
-+
-+ mbdebug("found extent %d:%d\n", start, len);
-+ tmp = start + group * EXT3_BLOCKS_PER_GROUP(as->sb)
-+ + le32_to_cpu(es->s_first_data_block);
-+
-+ /* account requests in order to limit searching */
-+ as->num++;
-+
-+ if (as->num == 20)
-+ return 1;
-+
-+ /* if hit goal, then searching may complete right now */
-+ if (tmp == as->goal) {
-+nice:
-+ as->start = tmp;
-+ as->len = len;
-+ return 1;
-+ }
-+
-+ /* if found extent has length we need, return it right now */
-+ if (as->target_len == len)
-+ goto nice;
-+
-+ /* first, check is found extent better than we have in as */
-+ if (as->len > len) {
-+better:
-+ as->start = tmp;
-+ as->len = len;
-+ return 0;
-+ }
-+
-+ /* FIXME: more checks! */
-+ as->start = tmp;
-+ as->len = len;
-+
-+ /* 1) closeness to goal */
-+
-+ /* 2) extent length */
-+ /* 3) number of tested extent (we check all found extents) */
-+ /* */
-+ return 0;
-+}
-+
-+/*
-+ * this routine tries to find upto *len free contig. blocks
-+ * return number of found block (+ length of extent in *len)
-+ * or -1 if no free blocks at all
-+ */
-+int ext3_find_free_extent(struct buffer_head *bh, int goal, int *len, int max)
-+{
-+ int i, l = 0;
-+
-+repeat:
-+ if (goal >= max)
-+ return -1;
-+ /* find first free block */
-+ i = ext3_find_next_zero_bit(bh->b_data, max, goal);
-+ if (i >= max) {
-+ /* no free block */
-+ return -1;
-+ }
-+ /* check upto len block for ability to be allocated */
-+ while (l < *len && i + l < max) {
-+ if (!ext3_test_allocatable(i + l, bh))
-+ break;
-+ l++;
-+ }
-+ if (l == 0) {
-+ goal = i + 1;
-+ goto repeat;
-+ }
-+ *len = l;
-+ return i;
-+}
-+
-+/*
-+ * this routine loops over group, finds free extents and tests them
-+ * for some criterias
-+ * it may return negative value if group can't be loaded, 0 - if
-+ * no good extent can be found, 1 - if good extent found
-+ */
-+int ext3_find_extent_in_group(struct alloc_status *as, int group,
-+ unsigned long goal, int len)
-+{
-+ int k, i, l, bitmap_nr, found = 0;
-+ struct super_block *sb = as->sb;
-+ int max = EXT3_BLOCKS_PER_GROUP(sb);
-+ struct buffer_head *bh, *bmbh;
-+ struct ext3_group_desc *gdp;
-+
-+ mbdebug("look for %d blocks in group %d starting from %lu\n",
-+ len, group, goal);
-+
-+ gdp = ext3_get_group_desc(as->sb, group, &bh);
-+ if (!gdp)
-+ return -EIO;
-+
-+ if (le16_to_cpu(gdp->bg_free_blocks_count) == 0)
-+ return 0;
-+
-+ bitmap_nr = load_block_bitmap(as->sb, group);
-+ if (bitmap_nr < 0)
-+ return -EIO;
-+
-+ bmbh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
-+
-+ i = goal;
-+ /* scan from goal to the end */
-+repeat:
-+ while (i < max) {
-+ l = len;
-+ k = ext3_find_free_extent(bmbh, i, &l, max);
-+ i = k + l;
-+ if (k < 0)
-+ break;
-+ if (ext3_test_extent(as, group, k, l)) {
-+ found = 1;
-+ goto out;
-+ }
-+ }
-+
-+ if (goal) {
-+ /* scan from 0 upto goal */
-+ mbdebug("repeat from %lu in %d\n", goal, group);
-+ max = goal - 1;
-+ goal = i = 0;
-+ goto repeat;
-+ }
-+out:
-+ return found;
-+}
-+
-+#define check_in_committed(bh,j) \
-+ J_ASSERT_BH((bh), !ext3_test_bit((j), bh2jh((bh))->b_committed_data))
-+
-+int ext3_new_blocks(handle_t *handle, struct inode *inode, int *num,
-+ unsigned long goal, int *errp)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ int first_group, group, bitmap_nr;
-+ struct buffer_head *bh, *bmbh;
-+ struct ext3_super_block *es;
-+ struct ext3_group_desc *gdp;
-+ struct alloc_status as;
-+ int err, bit, i;
-+
-+ J_ASSERT(num && *num > 0);
-+
-+ if (DQUOT_ALLOC_BLOCK(inode, *num)) {
-+ *errp = -EDQUOT;
-+ return 0;
-+ }
-+
-+ es = EXT3_SB(inode->i_sb)->s_es;
-+
-+ *errp = 0;
-+ as.target_len = *num;
-+ as.sb = sb;
-+ as.inode = inode;
-+ as.goal = goal;
-+ as.start = -1;
-+ as.len = 0;
-+ as.num = 0;
-+
-+ if (goal < le32_to_cpu(es->s_first_data_block) ||
-+ goal >= le32_to_cpu(es->s_blocks_count))
-+ goal = le32_to_cpu(es->s_first_data_block);
-+
-+ lock_super(sb);
-+ first_group = (goal - le32_to_cpu(es->s_first_data_block)) /
-+ EXT3_BLOCKS_PER_GROUP(sb);
-+ goal = (goal - le32_to_cpu(es->s_first_data_block)) %
-+ EXT3_BLOCKS_PER_GROUP(sb);
-+ group = first_group;
-+ do {
-+ err = ext3_find_extent_in_group(&as, group, goal, *num);
-+ if (err < 0)
-+ goto error_out;
-+ else if (err)
-+ break;
-+
-+ /* reset goal for next groups */
-+ goal = 0;
-+
-+ /* try next group */
-+ if (++group == EXT3_SB(sb)->s_groups_count)
-+ group = 0;
-+ } while (group != first_group);
-+
-+ if (as.len == 0) {
-+ err = -ENOSPC;
-+ goto error_out;
-+ }
-+
-+ /* in the end we've found something, allocate it */
-+ mbdebug("best extent: %u:%u\n", as.start, as.len);
-+
-+ group = (as.start - le32_to_cpu(es->s_first_data_block)) /
-+ EXT3_BLOCKS_PER_GROUP(sb);
-+ bit = (as.start - le32_to_cpu(es->s_first_data_block)) %
-+ EXT3_BLOCKS_PER_GROUP(sb);
-+ gdp = ext3_get_group_desc(sb, group, &bh);
-+ if (!gdp) {
-+ err = -EIO;
-+ goto error_out;
-+ }
-+
-+ /* mark block(s) used in bitmap ... */
-+ bitmap_nr = load_block_bitmap(sb, group);
-+ if (bitmap_nr < 0) {
-+ err = -EIO;
-+ goto error_out;
-+ }
-+ bmbh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
-+ /* Make sure we use undo access for the bitmap, because it is
-+ critical that we do the frozen_data COW on bitmap buffers in
-+ all cases even if the buffer is in BJ_Forget state in the
-+ committing transaction. */
-+ err = ext3_journal_get_undo_access(handle, bmbh);
-+ if (err)
-+ goto error_out;
-+ err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
-+ if (err)
-+ goto error_out;
-+ err = ext3_journal_get_write_access(handle, bh);
-+ if (err)
-+ goto error_out;
-+ for (i = 0; i < as.len; i++) {
-+ J_ASSERT(!ext3_test_bit(bit + i, bmbh->b_data));
-+ if (buffer_jbd(bmbh) && bh2jh(bmbh)->b_committed_data)
-+ check_in_committed(bmbh, bit + i);
-+ set_bit(bit + i, bmbh->b_data);
-+ }
-+ err = ext3_journal_dirty_metadata(handle, bmbh);
-+ if (err)
-+ goto error_out;
-+
-+ /* ... and correct group descriptor */
-+ gdp->bg_free_blocks_count =
-+ cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) - as.len);
-+ es->s_free_blocks_count =
-+ cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) - as.len);
-+ err = ext3_journal_dirty_metadata(handle, bmbh);
-+ if (err)
-+ goto error_out;
-+ err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
-+ if (err)
-+ goto error_out;
-+ sb->s_dirt = 1;
-+
-+ if (*num != as.len)
-+ DQUOT_FREE_BLOCK(inode, *num - as.len);
-+ *num = as.len;
-+
-+out:
-+ unlock_super(sb);
-+ return as.start;
-+
-+error_out:
-+ as.start = 0;
-+ *errp = err;
-+ goto out;
-+}
-+
-+EXPORT_SYMBOL(ext3_new_blocks);
-+
-Index: linux-2.4.24/fs/ext3/file.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/file.c 2004-01-31 02:06:18.000000000 +0300
-+++ linux-2.4.24/fs/ext3/file.c 2004-02-06 10:20:46.000000000 +0300
-@@ -69,6 +69,18 @@
- int err;
- struct inode *inode = file->f_dentry->d_inode;
-
-+#if 0
-+ /* allocate all the space to be written */
-+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) {
-+ int blocksize = inode->i_sb->s_blocksize;
-+ unsigned long start, end;
-+
-+ start = (unsigned long) *ppos / blocksize;
-+ end = ((unsigned long) *ppos + count + blocksize - 1)
-+ / blocksize;
-+ ext3_ext_allocate_nblocks(inode, start, end - start);
-+ }
-+#endif
- ret = generic_file_write(file, buf, count, ppos);
-
- /* Skip file flushing code if there was an error, or if nothing
-Index: linux-2.4.24/fs/ext3/Makefile
-===================================================================
---- linux-2.4.24.orig/fs/ext3/Makefile 2004-02-05 18:44:25.000000000 +0300
-+++ linux-2.4.24/fs/ext3/Makefile 2004-02-06 10:20:46.000000000 +0300
-@@ -14,7 +14,7 @@
- obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
- ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o \
- xattr_trusted.o extents.o
--export-objs += extents.o
-+export-objs += extents.o balloc.o
-
- obj-m := $(O_TARGET)
-
-Index: linux-2.4.24/include/linux/ext3_fs.h
-===================================================================
---- linux-2.4.24.orig/include/linux/ext3_fs.h 2004-01-30 00:09:37.000000000 +0300
-+++ linux-2.4.24/include/linux/ext3_fs.h 2004-02-06 10:20:46.000000000 +0300
-@@ -58,6 +58,8 @@
- #define ext3_debug(f, a...) do {} while (0)
- #endif
-
-+#define EXT3_MULTIBLOCK_ALLOCATOR 1
-+
- /*
- * Special inodes numbers
- */
-@@ -667,6 +669,7 @@
- extern struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb,
- unsigned int block_group,
- struct buffer_head ** bh);
-+extern int ext3_new_blocks(handle_t*, struct inode*, int*, unsigned long, int*);
-
- /* dir.c */
- extern int ext3_check_dir_entry(const char *, struct inode *,
+++ /dev/null
-Index: linux-2.4.24/fs/ext3/mballoc.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/mballoc.c 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.24/fs/ext3/mballoc.c 2004-08-06 04:50:53.000000000 +0400
-@@ -0,0 +1,1399 @@
-+/*
-+ * Copyright (c) 2004, Cluster File Systems, Inc, info@clusterfs.com
-+ * Written by Alex Tomas <alex@clusterfs.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public Licens
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-
-+ */
-+
-+
-+/*
-+ * mballoc.c contains the multiblocks allocation routines
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/time.h>
-+#include <linux/fs.h>
-+#include <linux/locks.h>
-+#include <linux/jbd.h>
-+#include <linux/slab.h>
-+#include <linux/ext3_fs.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/quotaops.h>
-+
-+/*
-+ * TODO:
-+ * - do not scan from the beginning, try to remember first free block
-+ * - mb_mark_used_* may allocate chunk right after splitting buddy
-+ * - special flag to advice allocator to look for requested + N blocks
-+ * this may improve interaction between extents and mballoc
-+ */
-+
-+/*
-+ * with AGRESSIVE_CHECK allocator runs consistency checks over
-+ * structures. this checks slow things down a lot
-+ */
-+#define AGGRESSIVE_CHECK__
-+
-+/*
-+ */
-+#define MB_DEBUG__
-+#ifdef MB_DEBUG
-+#define mb_debug(fmt,a...) printk(fmt, ##a)
-+#else
-+#define mb_debug(fmt,a...)
-+#endif
-+
-+/*
-+ * where to save buddies structures beetween umount/mount (clean case only)
-+ */
-+#define EXT3_BUDDY_FILE ".buddy"
-+
-+/*
-+ * max. number of chunks to be tracked in ext3_free_extent struct
-+ */
-+#define MB_ARR_SIZE 32
-+
-+struct ext3_allocation_context {
-+ struct super_block *ac_sb;
-+
-+ /* search goals */
-+ int ac_g_group;
-+ int ac_g_start;
-+ int ac_g_len;
-+ int ac_g_flags;
-+
-+ /* the best found extent */
-+ int ac_b_group;
-+ int ac_b_start;
-+ int ac_b_len;
-+
-+ /* number of iterations done. we have to track to limit searching */
-+ int ac_repeats;
-+ int ac_groups_scanned;
-+ int ac_status;
-+};
-+
-+#define AC_STATUS_CONTINUE 1
-+#define AC_STATUS_FOUND 2
-+
-+
-+struct ext3_buddy {
-+ void *bd_bitmap;
-+ void *bd_buddy;
-+ int bd_blkbits;
-+ struct buffer_head *bd_bh;
-+ struct buffer_head *bd_bh2;
-+ struct ext3_buddy_group_blocks *bd_bd;
-+ struct super_block *bd_sb;
-+};
-+
-+struct ext3_free_extent {
-+ int fe_start;
-+ int fe_len;
-+ unsigned char fe_orders[MB_ARR_SIZE];
-+ unsigned char fe_nums;
-+ unsigned char fe_back;
-+};
-+
-+#define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1)
-+
-+
-+int ext3_create (struct inode *, struct dentry *, int, struct nameidata *);
-+void ext3_free_blocks_old(handle_t *, struct inode *, unsigned long, unsigned long);
-+int ext3_new_block_old(handle_t *, struct inode *, unsigned long, u32 *, u32 *, int *);
-+int ext3_mb_reserve_blocks(struct super_block *, int);
-+void ext3_mb_release_blocks(struct super_block *, int);
-+void ext3_mb_poll_new_transaction(struct super_block *, handle_t *);
-+void ext3_mb_free_committed_blocks(struct super_block *);
-+int load_block_bitmap (struct super_block *, unsigned int);
-+
-+struct buffer_head *
-+read_block_bitmap_bh(struct super_block *sb, unsigned int block_group)
-+{
-+ struct buffer_head *bh;
-+ int bitmap_nr;
-+
-+ bitmap_nr = load_block_bitmap(sb, block_group);
-+ if (bitmap_nr < 0)
-+ return NULL;
-+
-+ bh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
-+ return bh;
-+}
-+
-+static inline void *mb_find_buddy(struct ext3_buddy *e3b, int order, int *max)
-+{
-+ int i = 1;
-+ void *bb;
-+
-+ J_ASSERT(e3b->bd_bitmap != e3b->bd_buddy);
-+ J_ASSERT(max != NULL);
-+
-+ if (order > e3b->bd_blkbits + 1)
-+ return NULL;
-+
-+ /* at order 0 we see each particular block */
-+ *max = 1 << (e3b->bd_blkbits + 3);
-+ if (order == 0)
-+ return e3b->bd_bitmap;
-+
-+ bb = e3b->bd_buddy;
-+ *max = *max >> 1;
-+ while (i < order) {
-+ bb += 1 << (e3b->bd_blkbits - i);
-+ i++;
-+ *max = *max >> 1;
-+ }
-+ return bb;
-+}
-+
-+static int ext3_mb_load_desc(struct super_block *sb, int group,
-+ struct ext3_buddy *e3b)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+
-+ J_ASSERT(sbi->s_buddy_blocks[group].bb_bitmap);
-+ J_ASSERT(sbi->s_buddy_blocks[group].bb_buddy);
-+
-+ /* load bitmap */
-+ e3b->bd_bh = sb_getblk(sb, sbi->s_buddy_blocks[group].bb_bitmap);
-+ if (e3b->bd_bh == NULL) {
-+ ext3_error(sb, "ext3_mb_load_desc",
-+ "can't get block for buddy bitmap\n");
-+ goto out;
-+ }
-+ if (!buffer_uptodate(e3b->bd_bh)) {
-+ ll_rw_block(READ, 1, &e3b->bd_bh);
-+ wait_on_buffer(e3b->bd_bh);
-+ }
-+ J_ASSERT(buffer_uptodate(e3b->bd_bh));
-+
-+ /* load buddy */
-+ e3b->bd_bh2 = sb_getblk(sb, sbi->s_buddy_blocks[group].bb_buddy);
-+ if (e3b->bd_bh2 == NULL) {
-+ ext3_error(sb, "ext3_mb_load_desc",
-+ "can't get block for buddy bitmap\n");
-+ goto out;
-+ }
-+ if (!buffer_uptodate(e3b->bd_bh2)) {
-+ ll_rw_block(READ, 1, &e3b->bd_bh2);
-+ wait_on_buffer(e3b->bd_bh2);
-+ }
-+ J_ASSERT(buffer_uptodate(e3b->bd_bh2));
-+
-+ e3b->bd_bitmap = e3b->bd_bh->b_data;
-+ e3b->bd_buddy = e3b->bd_bh2->b_data;
-+ e3b->bd_blkbits = sb->s_blocksize_bits;
-+ e3b->bd_bd = sbi->s_buddy_blocks + group;
-+ e3b->bd_sb = sb;
-+
-+ return 0;
-+out:
-+ brelse(e3b->bd_bh);
-+ brelse(e3b->bd_bh2);
-+ e3b->bd_bh = NULL;
-+ e3b->bd_bh2 = NULL;
-+ return -EIO;
-+}
-+
-+static void ext3_mb_dirty_buddy(struct ext3_buddy *e3b)
-+{
-+ mark_buffer_dirty(e3b->bd_bh);
-+ mark_buffer_dirty(e3b->bd_bh2);
-+}
-+
-+static void ext3_mb_release_desc(struct ext3_buddy *e3b)
-+{
-+ brelse(e3b->bd_bh);
-+ brelse(e3b->bd_bh2);
-+}
-+
-+#ifdef AGGRESSIVE_CHECK
-+static void mb_check_buddy(struct ext3_buddy *e3b)
-+{
-+ int order = e3b->bd_blkbits + 1;
-+ int max, max2, i, j, k, count;
-+ void *buddy, *buddy2;
-+
-+ if (!test_opt(e3b->bd_sb, MBALLOC))
-+ return;
-+
-+ while (order > 1) {
-+ buddy = mb_find_buddy(e3b, order, &max);
-+ J_ASSERT(buddy);
-+ buddy2 = mb_find_buddy(e3b, order - 1, &max2);
-+ J_ASSERT(buddy2);
-+ J_ASSERT(buddy != buddy2);
-+ J_ASSERT(max * 2 == max2);
-+
-+ count = 0;
-+ for (i = 0; i < max; i++) {
-+
-+ if (!test_bit(i, buddy)) {
-+ /* only single bit in buddy2 may be 1 */
-+ if (test_bit(i << 1, buddy2))
-+ J_ASSERT(!test_bit((i<<1)+1, buddy2));
-+ else if (test_bit((i << 1) + 1, buddy2))
-+ J_ASSERT(!test_bit(i << 1, buddy2));
-+ continue;
-+ }
-+
-+ /* both bits in buddy2 must be 0 */
-+ J_ASSERT(!test_bit(i << 1, buddy2));
-+ J_ASSERT(!test_bit((i << 1) + 1, buddy2));
-+
-+ for (j = 0; j < (1 << order); j++) {
-+ k = (i * (1 << order)) + j;
-+ J_ASSERT(test_bit(k, e3b->bd_bitmap));
-+ }
-+ count++;
-+ }
-+ J_ASSERT(e3b->bd_bd->bb_counters[order] == count);
-+ order--;
-+ }
-+
-+ buddy = mb_find_buddy(e3b, 0, &max);
-+ for (i = 0; i < max; i++) {
-+ if (test_bit(i, buddy))
-+ continue;
-+ /* check used bits only */
-+ for (j = 0; j < e3b->bd_blkbits + 1; j++) {
-+ buddy2 = mb_find_buddy(e3b, j, &max2);
-+ k = i >> j;
-+ J_ASSERT(k < max2);
-+ J_ASSERT(!test_bit(k, buddy2));
-+ }
-+ }
-+}
-+#else
-+#define mb_check_buddy(e3b)
-+#endif
-+
-+static inline void
-+ext3_lock_group(struct super_block *sb, int group)
-+{
-+ spin_lock(&EXT3_SB(sb)->s_buddy_blocks[group].bb_lock);
-+}
-+
-+static inline void
-+ext3_unlock_group(struct super_block *sb, int group)
-+{
-+ spin_unlock(&EXT3_SB(sb)->s_buddy_blocks[group].bb_lock);
-+}
-+
-+static int mb_find_order_for_block(struct ext3_buddy *e3b, int block)
-+{
-+ int order = 1;
-+ void *bb;
-+
-+ J_ASSERT(e3b->bd_bitmap != e3b->bd_buddy);
-+ J_ASSERT(block < (1 << (e3b->bd_blkbits + 3)));
-+
-+ bb = e3b->bd_buddy;
-+ while (order <= e3b->bd_blkbits + 1) {
-+ block = block >> 1;
-+ if (test_bit(block, bb)) {
-+ /* this block is part of buddy of order 'order' */
-+ return order;
-+ }
-+ bb += 1 << (e3b->bd_blkbits - order);
-+ order++;
-+ }
-+ return 0;
-+}
-+
-+static inline void mb_clear_bits(void *bm, int cur, int len)
-+{
-+ __u32 *addr;
-+
-+ len = cur + len;
-+ while (cur < len) {
-+ if ((cur & 31) == 0 && (len - cur) >= 32) {
-+ /* fast path: clear whole word at once */
-+ addr = bm + (cur >> 3);
-+ *addr = 0;
-+ cur += 32;
-+ continue;
-+ }
-+ clear_bit(cur, bm);
-+ cur++;
-+ }
-+}
-+
-+static inline void mb_set_bits(void *bm, int cur, int len)
-+{
-+ __u32 *addr;
-+
-+ len = cur + len;
-+ while (cur < len) {
-+ if ((cur & 31) == 0 && (len - cur) >= 32) {
-+ /* fast path: clear whole word at once */
-+ addr = bm + (cur >> 3);
-+ *addr = 0xffffffff;
-+ cur += 32;
-+ continue;
-+ }
-+ set_bit(cur, bm);
-+ cur++;
-+ }
-+}
-+
-+static int mb_free_blocks(struct ext3_buddy *e3b, int first, int count)
-+{
-+ int block, max, order;
-+ void *buddy, *buddy2;
-+
-+ mb_check_buddy(e3b);
-+ while (count-- > 0) {
-+ block = first++;
-+ order = 0;
-+
-+ J_ASSERT(!test_bit(block, e3b->bd_bitmap));
-+ set_bit(block, e3b->bd_bitmap);
-+ e3b->bd_bd->bb_counters[order]++;
-+
-+ /* start of the buddy */
-+ buddy = mb_find_buddy(e3b, order, &max);
-+
-+ do {
-+ block &= ~1UL;
-+ if (!test_bit(block, buddy) ||
-+ !test_bit(block + 1, buddy))
-+ break;
-+
-+ /* both the buddies are free, try to coalesce them */
-+ buddy2 = mb_find_buddy(e3b, order + 1, &max);
-+
-+ if (!buddy2)
-+ break;
-+
-+ if (order > 0) {
-+ /* for special purposes, we don't clear
-+ * free bits in bitmap */
-+ clear_bit(block, buddy);
-+ clear_bit(block + 1, buddy);
-+ }
-+ e3b->bd_bd->bb_counters[order]--;
-+ e3b->bd_bd->bb_counters[order]--;
-+
-+ block = block >> 1;
-+ order++;
-+ e3b->bd_bd->bb_counters[order]++;
-+
-+ set_bit(block, buddy2);
-+ buddy = buddy2;
-+ } while (1);
-+ }
-+ mb_check_buddy(e3b);
-+
-+ return 0;
-+}
-+
-+/*
-+ * returns 1 if out extent is enough to fill needed space
-+ */
-+int mb_make_backward_extent(struct ext3_free_extent *in,
-+ struct ext3_free_extent *out, int needed)
-+{
-+ int i;
-+
-+ J_ASSERT(in);
-+ J_ASSERT(out);
-+ J_ASSERT(in->fe_nums < MB_ARR_SIZE);
-+
-+ out->fe_len = 0;
-+ out->fe_start = in->fe_start + in->fe_len;
-+ out->fe_nums = 0;
-+
-+ /* for single-chunk extent we need not back order
-+ * also, if an extent doesn't fill needed space
-+ * then it makes no sense to try back order becase
-+ * if we select this extent then it'll be use as is */
-+ if (in->fe_nums < 2 || in->fe_len < needed)
-+ return 0;
-+
-+ i = in->fe_nums - 1;
-+ while (i >= 0 && out->fe_len < needed) {
-+ out->fe_len += (1 << in->fe_orders[i]);
-+ out->fe_start -= (1 << in->fe_orders[i]);
-+ i--;
-+ }
-+ /* FIXME: in some situation fe_orders may be too small to hold
-+ * all the buddies */
-+ J_ASSERT(out->fe_len >= needed);
-+
-+ for (i++; i < in->fe_nums; i++)
-+ out->fe_orders[out->fe_nums++] = in->fe_orders[i];
-+ J_ASSERT(out->fe_nums < MB_ARR_SIZE);
-+ out->fe_back = 1;
-+
-+ return 1;
-+}
-+
-+int mb_find_extent(struct ext3_buddy *e3b, int order, int block,
-+ int needed, struct ext3_free_extent *ex)
-+{
-+ int space = needed;
-+ int next, max, ord;
-+ void *buddy;
-+
-+ J_ASSERT(ex != NULL);
-+
-+ ex->fe_nums = 0;
-+ ex->fe_len = 0;
-+
-+ buddy = mb_find_buddy(e3b, order, &max);
-+ J_ASSERT(buddy);
-+ J_ASSERT(block < max);
-+ if (!test_bit(block, buddy))
-+ goto nofree;
-+
-+ if (order == 0) {
-+ /* find actual order */
-+ order = mb_find_order_for_block(e3b, block);
-+ block = block >> order;
-+ }
-+
-+ ex->fe_orders[ex->fe_nums++] = order;
-+ ex->fe_len = 1 << order;
-+ ex->fe_start = block << order;
-+ ex->fe_back = 0;
-+
-+ while ((space = space - (1 << order)) > 0) {
-+
-+ buddy = mb_find_buddy(e3b, order, &max);
-+ J_ASSERT(buddy);
-+
-+ if (block + 1 >= max)
-+ break;
-+
-+ next = (block + 1) * (1 << order);
-+ if (!test_bit(next, e3b->bd_bitmap))
-+ break;
-+
-+ ord = mb_find_order_for_block(e3b, next);
-+
-+ if ((1 << ord) >= needed) {
-+ /* we dont want to coalesce with self-enough buddies */
-+ break;
-+ }
-+ order = ord;
-+ block = next >> order;
-+ ex->fe_len += 1 << order;
-+
-+ if (ex->fe_nums < MB_ARR_SIZE)
-+ ex->fe_orders[ex->fe_nums++] = order;
-+ }
-+
-+nofree:
-+ J_ASSERT(ex->fe_start + ex->fe_len <= (1 << (e3b->bd_blkbits + 3)));
-+ return ex->fe_len;
-+}
-+
-+static int mb_mark_used_backward(struct ext3_buddy *e3b,
-+ struct ext3_free_extent *ex, int len)
-+{
-+ int start = ex->fe_start, len0 = len;
-+ int ord, mlen, max, cur;
-+ void *buddy;
-+
-+ start = ex->fe_start + ex->fe_len - 1;
-+ while (len) {
-+ ord = mb_find_order_for_block(e3b, start);
-+ if (((start >> ord) << ord) == (start - (1 << ord) + 1) &&
-+ len >= (1 << ord)) {
-+ /* the whole chunk may be allocated at once! */
-+ mlen = 1 << ord;
-+ buddy = mb_find_buddy(e3b, ord, &max);
-+ J_ASSERT((start >> ord) < max);
-+ clear_bit(start >> ord, buddy);
-+ e3b->bd_bd->bb_counters[ord]--;
-+ start -= mlen;
-+ len -= mlen;
-+ J_ASSERT(len >= 0);
-+ J_ASSERT(start >= 0);
-+ continue;
-+ }
-+
-+ /* we have to split large buddy */
-+ J_ASSERT(ord > 0);
-+ buddy = mb_find_buddy(e3b, ord, &max);
-+ clear_bit(start >> ord, buddy);
-+ e3b->bd_bd->bb_counters[ord]--;
-+
-+ ord--;
-+ cur = (start >> ord) & ~1U;
-+ buddy = mb_find_buddy(e3b, ord, &max);
-+ set_bit(cur, buddy);
-+ set_bit(cur + 1, buddy);
-+ e3b->bd_bd->bb_counters[ord]++;
-+ e3b->bd_bd->bb_counters[ord]++;
-+ }
-+
-+ /* now drop all the bits in bitmap */
-+ mb_clear_bits(e3b->bd_bitmap, ex->fe_start + ex->fe_len - len0, len0);
-+
-+ mb_check_buddy(e3b);
-+
-+ return 0;
-+}
-+
-+static int mb_mark_used_forward(struct ext3_buddy *e3b,
-+ struct ext3_free_extent *ex, int len)
-+{
-+ int start = ex->fe_start, len0 = len;
-+ int ord, mlen, max, cur;
-+ void *buddy;
-+
-+ while (len) {
-+ ord = mb_find_order_for_block(e3b, start);
-+
-+ if (((start >> ord) << ord) == start && len >= (1 << ord)) {
-+ /* the whole chunk may be allocated at once! */
-+ mlen = 1 << ord;
-+ buddy = mb_find_buddy(e3b, ord, &max);
-+ J_ASSERT((start >> ord) < max);
-+ clear_bit(start >> ord, buddy);
-+ e3b->bd_bd->bb_counters[ord]--;
-+ start += mlen;
-+ len -= mlen;
-+ J_ASSERT(len >= 0);
-+ continue;
-+ }
-+
-+ /* we have to split large buddy */
-+ J_ASSERT(ord > 0);
-+ buddy = mb_find_buddy(e3b, ord, &max);
-+ clear_bit(start >> ord, buddy);
-+ e3b->bd_bd->bb_counters[ord]--;
-+
-+ ord--;
-+ cur = (start >> ord) & ~1U;
-+ buddy = mb_find_buddy(e3b, ord, &max);
-+ set_bit(cur, buddy);
-+ set_bit(cur + 1, buddy);
-+ e3b->bd_bd->bb_counters[ord]++;
-+ e3b->bd_bd->bb_counters[ord]++;
-+ }
-+
-+ /* now drop all the bits in bitmap */
-+ mb_clear_bits(e3b->bd_bitmap, ex->fe_start, len0);
-+
-+ mb_check_buddy(e3b);
-+
-+ return 0;
-+}
-+
-+int inline mb_mark_used(struct ext3_buddy *e3b,
-+ struct ext3_free_extent *ex, int len)
-+{
-+ int err;
-+
-+ J_ASSERT(ex);
-+ if (ex->fe_back == 0)
-+ err = mb_mark_used_forward(e3b, ex, len);
-+ else
-+ err = mb_mark_used_backward(e3b, ex, len);
-+ return err;
-+}
-+
-+int ext3_mb_new_in_group(struct ext3_allocation_context *ac,
-+ struct ext3_buddy *e3b, int group)
-+{
-+ struct super_block *sb = ac->ac_sb;
-+ int err, gorder, max, i;
-+ struct ext3_free_extent curex;
-+
-+ /* let's know order of allocation */
-+ gorder = 0;
-+ while (ac->ac_g_len > (1 << gorder))
-+ gorder++;
-+
-+ if ((ac->ac_g_flags & 1) && ac->ac_g_group == group) {
-+ /* someone asks for space at this specified block
-+ * probably he wants to merge it into existing extent */
-+ if (test_bit(ac->ac_g_start, e3b->bd_bitmap)) {
-+ /* good. at least one block is free */
-+ max = mb_find_extent(e3b, 0, ac->ac_g_start,
-+ ac->ac_g_len, &curex);
-+ max = min(curex.fe_len, ac->ac_g_len);
-+ mb_mark_used(e3b, &curex, max);
-+
-+ ac->ac_b_group = group;
-+ ac->ac_b_start = curex.fe_start;
-+ ac->ac_b_len = max;
-+ ac->ac_status = AC_STATUS_FOUND;
-+ err = 0;
-+ goto out;
-+ }
-+ /* don't try to find goal anymore */
-+ ac->ac_g_flags &= ~1;
-+ }
-+
-+ i = 0;
-+ while (1) {
-+ i = find_next_bit(e3b->bd_bitmap, sb->s_blocksize * 8, i);
-+ if (i >= sb->s_blocksize * 8)
-+ break;
-+
-+ max = mb_find_extent(e3b, 0, i, ac->ac_g_len, &curex);
-+ if (max >= ac->ac_g_len) {
-+ max = min(curex.fe_len, ac->ac_g_len);
-+ mb_mark_used(e3b, &curex, max);
-+
-+ ac->ac_b_group = group;
-+ ac->ac_b_start = curex.fe_start;
-+ ac->ac_b_len = max;
-+ ac->ac_status = AC_STATUS_FOUND;
-+ break;
-+ }
-+ i += max;
-+ }
-+
-+ return 0;
-+
-+out:
-+ return err;
-+}
-+
-+int mb_good_group(struct ext3_allocation_context *ac, int group, int cr)
-+{
-+ struct ext3_group_desc *gdp;
-+ int free_blocks;
-+
-+ gdp = ext3_get_group_desc(ac->ac_sb, group, NULL);
-+ if (!gdp)
-+ return 0;
-+ free_blocks = le16_to_cpu(gdp->bg_free_blocks_count);
-+ if (free_blocks == 0)
-+ return 0;
-+
-+ /* someone wants this block very much */
-+ if ((ac->ac_g_flags & 1) && ac->ac_g_group == group)
-+ return 1;
-+
-+ /* FIXME: I'd like to take fragmentation into account here */
-+ if (cr == 0) {
-+ if (free_blocks >= ac->ac_g_len >> 1)
-+ return 1;
-+ } else if (cr == 1) {
-+ if (free_blocks >= ac->ac_g_len >> 2)
-+ return 1;
-+ } else if (cr == 2) {
-+ return 1;
-+ } else {
-+ BUG();
-+ }
-+ return 0;
-+}
-+
-+int ext3_mb_new_blocks(handle_t *handle, struct inode *inode,
-+ unsigned long goal, int *len, int flags, int *errp)
-+{
-+ struct buffer_head *bitmap_bh = NULL;
-+ struct ext3_allocation_context ac;
-+ int i, group, block, cr, err = 0;
-+ struct ext3_group_desc *gdp;
-+ struct ext3_super_block *es;
-+ struct buffer_head *gdp_bh;
-+ struct ext3_sb_info *sbi;
-+ struct super_block *sb;
-+ struct ext3_buddy e3b;
-+
-+ J_ASSERT(len != NULL);
-+ J_ASSERT(*len > 0);
-+
-+ sb = inode->i_sb;
-+ if (!sb) {
-+ printk("ext3_mb_new_nblocks: nonexistent device");
-+ return 0;
-+ }
-+
-+ ext3_mb_poll_new_transaction(sb, handle);
-+
-+ sbi = EXT3_SB(sb);
-+ es = EXT3_SB(sb)->s_es;
-+
-+ if (!(flags & 2)) {
-+ /* someone asks for non-reserved blocks */
-+ BUG_ON(*len > 1);
-+ err = ext3_mb_reserve_blocks(sb, 1);
-+ if (err) {
-+ *errp = err;
-+ return 0;
-+ }
-+ }
-+
-+ /*
-+ * Check quota for allocation of this blocks.
-+ */
-+ while (*len && DQUOT_ALLOC_BLOCK(inode, *len))
-+ *len -= 1;
-+ if (*len == 0) {
-+ *errp = -EDQUOT;
-+ block = 0;
-+ goto out;
-+ }
-+
-+ /* start searching from the goal */
-+ if (goal < le32_to_cpu(es->s_first_data_block) ||
-+ goal >= le32_to_cpu(es->s_blocks_count))
-+ goal = le32_to_cpu(es->s_first_data_block);
-+ group = (goal - le32_to_cpu(es->s_first_data_block)) /
-+ EXT3_BLOCKS_PER_GROUP(sb);
-+ block = ((goal - le32_to_cpu(es->s_first_data_block)) %
-+ EXT3_BLOCKS_PER_GROUP(sb));
-+
-+ /* set up allocation goals */
-+ ac.ac_b_group = ac.ac_b_start = ac.ac_b_len = 0;
-+ ac.ac_status = 0;
-+ ac.ac_groups_scanned = 0;
-+ ac.ac_sb = inode->i_sb;
-+ ac.ac_g_group = group;
-+ ac.ac_g_start = block;
-+ ac.ac_g_len = *len;
-+ ac.ac_g_flags = flags;
-+
-+ /* loop over the groups */
-+ for (cr = 0; cr < 3 && ac.ac_status != AC_STATUS_FOUND; cr++) {
-+ for (i = 0; i < EXT3_SB(sb)->s_groups_count; group++, i++) {
-+ if (group == EXT3_SB(sb)->s_groups_count)
-+ group = 0;
-+
-+ /* check is group good for our criteries */
-+ if (!mb_good_group(&ac, group, cr))
-+ continue;
-+
-+ err = ext3_mb_load_desc(ac.ac_sb, group, &e3b);
-+ if (err)
-+ goto out_err;
-+
-+ ext3_lock_group(sb, group);
-+ if (!mb_good_group(&ac, group, cr)) {
-+ /* someone did allocation from this group */
-+ ext3_unlock_group(sb, group);
-+ ext3_mb_release_desc(&e3b);
-+ continue;
-+ }
-+
-+ err = ext3_mb_new_in_group(&ac, &e3b, group);
-+ ext3_unlock_group(sb, group);
-+ if (ac.ac_status == AC_STATUS_FOUND)
-+ ext3_mb_dirty_buddy(&e3b);
-+ ext3_mb_release_desc(&e3b);
-+ if (err)
-+ goto out_err;
-+ if (ac.ac_status == AC_STATUS_FOUND)
-+ break;
-+ }
-+ }
-+
-+ if (ac.ac_status != AC_STATUS_FOUND) {
-+ /* unfortunately, we can't satisfy this request */
-+ J_ASSERT(ac.ac_b_len == 0);
-+ DQUOT_FREE_BLOCK(inode, *len);
-+ *errp = -ENOSPC;
-+ block = 0;
-+ goto out;
-+ }
-+
-+ /* good news - free block(s) have been found. now it's time
-+ * to mark block(s) in good old journaled bitmap */
-+ block = ac.ac_b_group * EXT3_BLOCKS_PER_GROUP(sb)
-+ + ac.ac_b_start + le32_to_cpu(es->s_first_data_block);
-+
-+ /* we made a desicion, now mark found blocks in good old
-+ * bitmap to be journaled */
-+
-+ ext3_debug("using block group %d(%d)\n",
-+ ac.ac_b_group.group, gdp->bg_free_blocks_count);
-+
-+ bitmap_bh = read_block_bitmap_bh(sb, ac.ac_b_group);
-+ if (!bitmap_bh) {
-+ *errp = -EIO;
-+ goto out_err;
-+ }
-+
-+ err = ext3_journal_get_write_access(handle, bitmap_bh);
-+ if (err) {
-+ *errp = err;
-+ goto out_err;
-+ }
-+
-+ gdp = ext3_get_group_desc(sb, ac.ac_b_group, &gdp_bh);
-+ if (!gdp) {
-+ *errp = -EIO;
-+ goto out_err;
-+ }
-+
-+ err = ext3_journal_get_write_access(handle, gdp_bh);
-+ if (err)
-+ goto out_err;
-+
-+ block = ac.ac_b_start + ac.ac_b_group * EXT3_BLOCKS_PER_GROUP(sb)
-+ + le32_to_cpu(es->s_first_data_block);
-+
-+ if (block == le32_to_cpu(gdp->bg_block_bitmap) ||
-+ block == le32_to_cpu(gdp->bg_inode_bitmap) ||
-+ in_range(block, le32_to_cpu(gdp->bg_inode_table),
-+ EXT3_SB(sb)->s_itb_per_group))
-+ ext3_error(sb, "ext3_new_block",
-+ "Allocating block in system zone - "
-+ "block = %u", block);
-+#if 0
-+ for (i = 0; i < ac.ac_b_len; i++)
-+ J_ASSERT(!test_bit(ac.ac_b_start + i, bitmap_bh->b_data));
-+#endif
-+ mb_set_bits(bitmap_bh->b_data, ac.ac_b_start, ac.ac_b_len);
-+
-+ ext3_lock_group(sb, ac.ac_b_group);
-+ gdp->bg_free_blocks_count =
-+ cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) -
-+ ac.ac_b_len);
-+ ext3_unlock_group(sb, ac.ac_b_group);
-+ spin_lock(&sbi->s_md_lock);
-+ es->s_free_blocks_count =
-+ cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) - ac.ac_b_len);
-+ spin_unlock(&sbi->s_md_lock);
-+
-+ err = ext3_journal_dirty_metadata(handle, bitmap_bh);
-+ if (err)
-+ goto out_err;
-+ err = ext3_journal_dirty_metadata(handle, gdp_bh);
-+ if (err)
-+ goto out_err;
-+
-+ sb->s_dirt = 1;
-+ *errp = 0;
-+
-+ /* drop non-allocated, but dquote'd blocks */
-+ J_ASSERT(*len >= ac.ac_b_len);
-+ DQUOT_FREE_BLOCK(inode, *len - ac.ac_b_len);
-+
-+ *len = ac.ac_b_len;
-+ J_ASSERT(block != 0);
-+ goto out;
-+
-+out_err:
-+ /* if we've already allocated something, roll it back */
-+ if (ac.ac_status == AC_STATUS_FOUND) {
-+ /* FIXME: free blocks here */
-+ }
-+
-+ DQUOT_FREE_BLOCK(inode, *len);
-+ *errp = err;
-+ block = 0;
-+out:
-+ if (!(flags & 2)) {
-+ /* block wasn't reserved before and we reserved it
-+ * at the beginning of allocation. it doesn't matter
-+ * whether we allocated anything or we failed: time
-+ * to release reservation. NOTE: because I expect
-+ * any multiblock request from delayed allocation
-+ * path only, here is single block always */
-+ ext3_mb_release_blocks(sb, 1);
-+ }
-+ return block;
-+}
-+
-+int ext3_mb_generate_buddy(struct super_block *sb, int group)
-+{
-+ struct buffer_head *bh;
-+ int i, err, count = 0;
-+ struct ext3_buddy e3b;
-+
-+ err = ext3_mb_load_desc(sb, group, &e3b);
-+ if (err)
-+ goto out;
-+ memset(e3b.bd_bh->b_data, 0, sb->s_blocksize);
-+ memset(e3b.bd_bh2->b_data, 0, sb->s_blocksize);
-+
-+ bh = read_block_bitmap_bh(sb, group);
-+ if (bh == NULL) {
-+ err = -EIO;
-+ goto out2;
-+ }
-+
-+ /* loop over the blocks, nad create buddies for free ones */
-+ for (i = 0; i < sb->s_blocksize * 8; i++) {
-+ if (!test_bit(i, (void *) bh->b_data)) {
-+ mb_free_blocks(&e3b, i, 1);
-+ count++;
-+ }
-+ }
-+ mb_check_buddy(&e3b);
-+ ext3_mb_dirty_buddy(&e3b);
-+
-+out2:
-+ ext3_mb_release_desc(&e3b);
-+out:
-+ return err;
-+}
-+
-+#define MB_CREDITS \
-+ (EXT3_DATA_TRANS_BLOCKS + 3 + EXT3_INDEX_EXTRA_TRANS_BLOCKS)
-+
-+int ext3_mb_init_backend(struct super_block *sb)
-+{
-+ struct inode *root = sb->s_root->d_inode;
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+ struct dentry *db;
-+ tid_t target;
-+ int err, i;
-+
-+ sbi->s_buddy_blocks = kmalloc(sizeof(struct ext3_buddy_group_blocks) *
-+ sbi->s_groups_count, GFP_KERNEL);
-+ if (sbi->s_buddy_blocks == NULL) {
-+ printk("can't allocate mem for buddy maps\n");
-+ return -ENOMEM;
-+ }
-+ memset(sbi->s_buddy_blocks, 0,
-+ sizeof(struct ext3_buddy_group_blocks) * sbi->s_groups_count);
-+ sbi->s_buddy = NULL;
-+
-+ down(&root->i_sem);
-+ db = lookup_one_len(EXT3_BUDDY_FILE, sb->s_root,
-+ strlen(EXT3_BUDDY_FILE));
-+ if (IS_ERR(db)) {
-+ err = PTR_ERR(db);
-+ printk("can't lookup buddy file: %d\n", err);
-+ goto out;
-+ }
-+
-+ if (db->d_inode != NULL) {
-+ sbi->s_buddy = igrab(db->d_inode);
-+ goto map;
-+ }
-+
-+ err = ext3_create(root, db, S_IFREG, NULL);
-+ if (err) {
-+ printk("error while creation buddy file: %d\n", err);
-+ } else {
-+ sbi->s_buddy = igrab(db->d_inode);
-+ }
-+
-+map:
-+ for (i = 0; i < sbi->s_groups_count; i++) {
-+ struct buffer_head *bh = NULL;
-+ handle_t *handle;
-+
-+ handle = ext3_journal_start(sbi->s_buddy, MB_CREDITS);
-+ if (IS_ERR(handle)) {
-+ err = PTR_ERR(handle);
-+ goto out2;
-+ }
-+
-+ /* allocate block for bitmap */
-+ bh = ext3_getblk(handle, sbi->s_buddy, i * 2, 1, &err);
-+ if (bh == NULL) {
-+ printk("can't get block for buddy bitmap: %d\n", err);
-+ goto out2;
-+ }
-+ sbi->s_buddy_blocks[i].bb_bitmap = bh->b_blocknr;
-+ brelse(bh);
-+
-+ /* allocate block for buddy */
-+ bh = ext3_getblk(handle, sbi->s_buddy, i * 2 + 1, 1, &err);
-+ if (bh == NULL) {
-+ printk("can't get block for buddy: %d\n", err);
-+ goto out2;
-+ }
-+ sbi->s_buddy_blocks[i].bb_buddy = bh->b_blocknr;
-+ brelse(bh);
-+ ext3_journal_stop(handle, sbi->s_buddy);
-+ spin_lock_init(&sbi->s_buddy_blocks[i].bb_lock);
-+ sbi->s_buddy_blocks[i].bb_md_cur = NULL;
-+ sbi->s_buddy_blocks[i].bb_tid = 0;
-+ }
-+
-+ if ((target = log_start_commit(sbi->s_journal, NULL)))
-+ log_wait_commit(sbi->s_journal, target);
-+
-+out2:
-+ dput(db);
-+out:
-+ up(&root->i_sem);
-+ return err;
-+}
-+
-+int ext3_mb_release(struct super_block *sb)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+
-+ if (!test_opt(sb, MBALLOC))
-+ return 0;
-+
-+ /* release freed, non-committed blocks */
-+ spin_lock(&sbi->s_md_lock);
-+ list_splice_init(&sbi->s_closed_transaction,
-+ &sbi->s_committed_transaction);
-+ list_splice_init(&sbi->s_active_transaction,
-+ &sbi->s_committed_transaction);
-+ spin_unlock(&sbi->s_md_lock);
-+ ext3_mb_free_committed_blocks(sb);
-+
-+ if (sbi->s_buddy_blocks)
-+ kfree(sbi->s_buddy_blocks);
-+ if (sbi->s_buddy)
-+ iput(sbi->s_buddy);
-+ if (sbi->s_blocks_reserved)
-+ printk("ext3-fs: %ld blocks being reserved at umount!\n",
-+ sbi->s_blocks_reserved);
-+ return 0;
-+}
-+
-+int ext3_mb_init(struct super_block *sb)
-+{
-+ struct ext3_super_block *es;
-+ int i;
-+
-+ if (!test_opt(sb, MBALLOC))
-+ return 0;
-+
-+ /* init file for buddy data */
-+ clear_opt(EXT3_SB(sb)->s_mount_opt, MBALLOC);
-+ ext3_mb_init_backend(sb);
-+
-+ es = EXT3_SB(sb)->s_es;
-+ for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++)
-+ ext3_mb_generate_buddy(sb, i);
-+ spin_lock_init(&EXT3_SB(sb)->s_reserve_lock);
-+ spin_lock_init(&EXT3_SB(sb)->s_md_lock);
-+ INIT_LIST_HEAD(&EXT3_SB(sb)->s_active_transaction);
-+ INIT_LIST_HEAD(&EXT3_SB(sb)->s_closed_transaction);
-+ INIT_LIST_HEAD(&EXT3_SB(sb)->s_committed_transaction);
-+ set_opt(EXT3_SB(sb)->s_mount_opt, MBALLOC);
-+ printk("EXT3-fs: mballoc enabled\n");
-+ return 0;
-+}
-+
-+void ext3_mb_free_committed_blocks(struct super_block *sb)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+ int err, i, count = 0, count2 = 0;
-+ struct ext3_free_metadata *md;
-+ struct ext3_buddy e3b;
-+
-+ if (list_empty(&sbi->s_committed_transaction))
-+ return;
-+
-+ /* there is committed blocks to be freed yet */
-+ do {
-+ /* get next array of blocks */
-+ md = NULL;
-+ spin_lock(&sbi->s_md_lock);
-+ if (!list_empty(&sbi->s_committed_transaction)) {
-+ md = list_entry(sbi->s_committed_transaction.next,
-+ struct ext3_free_metadata, list);
-+ list_del(&md->list);
-+ }
-+ spin_unlock(&sbi->s_md_lock);
-+
-+ if (md == NULL)
-+ break;
-+
-+ mb_debug("gonna free %u blocks in group %u (0x%p):",
-+ md->num, md->group, md);
-+
-+ err = ext3_mb_load_desc(sb, md->group, &e3b);
-+ BUG_ON(err != 0);
-+
-+ /* there are blocks to put in buddy to make them really free */
-+ count += md->num;
-+ count2++;
-+ ext3_lock_group(sb, md->group);
-+ for (i = 0; i < md->num; i++) {
-+ mb_debug(" %u", md->blocks[i]);
-+ mb_free_blocks(&e3b, md->blocks[i], 1);
-+ }
-+ mb_debug("\n");
-+ ext3_unlock_group(sb, md->group);
-+
-+ kfree(md);
-+ ext3_mb_dirty_buddy(&e3b);
-+ ext3_mb_release_desc(&e3b);
-+
-+ } while (md);
-+ mb_debug("freed %u blocks in %u structures\n", count, count2);
-+}
-+
-+void ext3_mb_poll_new_transaction(struct super_block *sb, handle_t *handle)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+
-+ if (sbi->s_last_transaction == handle->h_transaction->t_tid)
-+ return;
-+
-+ /* new transaction! time to close last one and free blocks for
-+ * committed transaction. we know that only transaction can be
-+ * active, so previos transaction can be being logged and we
-+ * know that transaction before previous is known to be alreade
-+ * logged. this means that now we may free blocks freed in all
-+ * transactions before previous one. hope I'm clear enough ... */
-+
-+ spin_lock(&sbi->s_md_lock);
-+ if (sbi->s_last_transaction != handle->h_transaction->t_tid) {
-+ mb_debug("new transaction %lu, old %lu\n",
-+ (unsigned long) handle->h_transaction->t_tid,
-+ (unsigned long) sbi->s_last_transaction);
-+ list_splice_init(&sbi->s_closed_transaction,
-+ &sbi->s_committed_transaction);
-+ list_splice_init(&sbi->s_active_transaction,
-+ &sbi->s_closed_transaction);
-+ sbi->s_last_transaction = handle->h_transaction->t_tid;
-+ }
-+ spin_unlock(&sbi->s_md_lock);
-+
-+ ext3_mb_free_committed_blocks(sb);
-+}
-+
-+int ext3_mb_free_metadata(handle_t *handle, struct ext3_buddy *e3b,
-+ int group, int block, int count)
-+{
-+ struct ext3_buddy_group_blocks *db = e3b->bd_bd;
-+ struct super_block *sb = e3b->bd_sb;
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+ struct ext3_free_metadata *md;
-+ int i;
-+
-+ ext3_lock_group(sb, group);
-+ for (i = 0; i < count; i++) {
-+ md = db->bb_md_cur;
-+ if (md && db->bb_tid != handle->h_transaction->t_tid) {
-+ db->bb_md_cur = NULL;
-+ md = NULL;
-+ }
-+
-+ if (md == NULL) {
-+ ext3_unlock_group(sb, group);
-+ md = kmalloc(sizeof(*md), GFP_KERNEL);
-+ if (md == NULL)
-+ return -ENOMEM;
-+ md->num = 0;
-+ md->group = group;
-+
-+ ext3_lock_group(sb, group);
-+ if (db->bb_md_cur == NULL) {
-+ spin_lock(&sbi->s_md_lock);
-+ list_add(&md->list, &sbi->s_active_transaction);
-+ spin_unlock(&sbi->s_md_lock);
-+ db->bb_md_cur = md;
-+ db->bb_tid = handle->h_transaction->t_tid;
-+ mb_debug("new md 0x%p for group %u\n",
-+ md, md->group);
-+ } else {
-+ kfree(md);
-+ md = db->bb_md_cur;
-+ }
-+ }
-+
-+ BUG_ON(md->num >= EXT3_BB_MAX_BLOCKS);
-+ md->blocks[md->num] = block + i;
-+ md->num++;
-+ if (md->num == EXT3_BB_MAX_BLOCKS) {
-+ /* no more space, put full container on a sb's list */
-+ db->bb_md_cur = NULL;
-+ }
-+ }
-+ ext3_unlock_group(sb, group);
-+ return 0;
-+}
-+
-+void ext3_mb_free_blocks(handle_t *handle, struct inode *inode,
-+ unsigned long block, unsigned long count, int metadata)
-+{
-+ struct buffer_head *bitmap_bh = NULL;
-+ struct ext3_group_desc *gdp;
-+ struct ext3_super_block *es;
-+ unsigned long bit, overflow;
-+ struct buffer_head *gd_bh;
-+ unsigned long block_group;
-+ struct ext3_sb_info *sbi;
-+ struct super_block *sb;
-+ struct ext3_buddy e3b;
-+ int err = 0, ret;
-+
-+ sb = inode->i_sb;
-+ if (!sb) {
-+ printk ("ext3_free_blocks: nonexistent device");
-+ return;
-+ }
-+
-+ ext3_mb_poll_new_transaction(sb, handle);
-+
-+ sbi = EXT3_SB(sb);
-+ es = EXT3_SB(sb)->s_es;
-+ if (block < le32_to_cpu(es->s_first_data_block) ||
-+ block + count < block ||
-+ block + count > le32_to_cpu(es->s_blocks_count)) {
-+ ext3_error (sb, "ext3_free_blocks",
-+ "Freeing blocks not in datazone - "
-+ "block = %lu, count = %lu", block, count);
-+ goto error_return;
-+ }
-+
-+ ext3_debug("freeing block %lu\n", block);
-+
-+do_more:
-+ overflow = 0;
-+ block_group = (block - le32_to_cpu(es->s_first_data_block)) /
-+ EXT3_BLOCKS_PER_GROUP(sb);
-+ bit = (block - le32_to_cpu(es->s_first_data_block)) %
-+ EXT3_BLOCKS_PER_GROUP(sb);
-+ /*
-+ * Check to see if we are freeing blocks across a group
-+ * boundary.
-+ */
-+ if (bit + count > EXT3_BLOCKS_PER_GROUP(sb)) {
-+ overflow = bit + count - EXT3_BLOCKS_PER_GROUP(sb);
-+ count -= overflow;
-+ }
-+ bitmap_bh = read_block_bitmap_bh(sb, block_group);
-+ if (!bitmap_bh)
-+ goto error_return;
-+ gdp = ext3_get_group_desc (sb, block_group, &gd_bh);
-+ if (!gdp)
-+ goto error_return;
-+
-+ if (in_range (le32_to_cpu(gdp->bg_block_bitmap), block, count) ||
-+ in_range (le32_to_cpu(gdp->bg_inode_bitmap), block, count) ||
-+ in_range (block, le32_to_cpu(gdp->bg_inode_table),
-+ EXT3_SB(sb)->s_itb_per_group) ||
-+ in_range (block + count - 1, le32_to_cpu(gdp->bg_inode_table),
-+ EXT3_SB(sb)->s_itb_per_group))
-+ ext3_error (sb, "ext3_free_blocks",
-+ "Freeing blocks in system zones - "
-+ "Block = %lu, count = %lu",
-+ block, count);
-+
-+ BUFFER_TRACE(bitmap_bh, "getting write access");
-+ err = ext3_journal_get_write_access(handle, bitmap_bh);
-+ if (err)
-+ goto error_return;
-+
-+ /*
-+ * We are about to modify some metadata. Call the journal APIs
-+ * to unshare ->b_data if a currently-committing transaction is
-+ * using it
-+ */
-+ BUFFER_TRACE(gd_bh, "get_write_access");
-+ err = ext3_journal_get_write_access(handle, gd_bh);
-+ if (err)
-+ goto error_return;
-+
-+ err = ext3_mb_load_desc(sb, block_group, &e3b);
-+ if (err)
-+ goto error_return;
-+
-+ if (metadata) {
-+ /* blocks being freed are metadata. these blocks shouldn't
-+ * be used until this transaction is committed */
-+ ext3_mb_free_metadata(handle, &e3b, block_group, bit, count);
-+ } else {
-+ ext3_lock_group(sb, block_group);
-+ mb_free_blocks(&e3b, bit, count);
-+ gdp->bg_free_blocks_count =
-+ cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) + count);
-+ ext3_unlock_group(sb, block_group);
-+ spin_lock(&sbi->s_md_lock);
-+ es->s_free_blocks_count =
-+ cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) + count);
-+ spin_unlock(&sbi->s_md_lock);
-+ }
-+
-+ ext3_mb_dirty_buddy(&e3b);
-+ ext3_mb_release_desc(&e3b);
-+
-+ /* FIXME: undo logic will be implemented later and another way */
-+ mb_clear_bits(bitmap_bh->b_data, bit, count);
-+ DQUOT_FREE_BLOCK(inode, count);
-+
-+ /* We dirtied the bitmap block */
-+ BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
-+ err = ext3_journal_dirty_metadata(handle, bitmap_bh);
-+
-+ /* And the group descriptor block */
-+ BUFFER_TRACE(gd_bh, "dirtied group descriptor block");
-+ ret = ext3_journal_dirty_metadata(handle, gd_bh);
-+ if (!err) err = ret;
-+
-+ if (overflow && !err) {
-+ block += count;
-+ count = overflow;
-+ goto do_more;
-+ }
-+ sb->s_dirt = 1;
-+error_return:
-+ ext3_std_error(sb, err);
-+ return;
-+}
-+
-+int ext3_mb_reserve_blocks(struct super_block *sb, int blocks)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+ struct ext3_super_block *es;
-+ int free, ret = -ENOSPC;
-+
-+ BUG_ON(blocks < 0);
-+ es = EXT3_SB(sb)->s_es;
-+ spin_lock(&sbi->s_reserve_lock);
-+ free = le32_to_cpu(es->s_free_blocks_count);
-+ if (blocks <= free - sbi->s_blocks_reserved) {
-+ sbi->s_blocks_reserved += blocks;
-+ ret = 0;
-+ }
-+ spin_unlock(&sbi->s_reserve_lock);
-+ return ret;
-+}
-+
-+void ext3_mb_release_blocks(struct super_block *sb, int blocks)
-+{
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+
-+ BUG_ON(blocks < 0);
-+ spin_lock(&sbi->s_reserve_lock);
-+ sbi->s_blocks_reserved -= blocks;
-+ if (sbi->s_blocks_reserved < 0)
-+ printk("EXT3-fs: reserve leak %ld\n", sbi->s_blocks_reserved);
-+ if (sbi->s_blocks_reserved < 0)
-+ sbi->s_blocks_reserved = 0;
-+ spin_unlock(&sbi->s_reserve_lock);
-+}
-+
-+int ext3_new_block(handle_t *handle, struct inode *inode,
-+ unsigned long goal, u32 *pc, u32 *pb, int *errp)
-+{
-+ int ret, len;
-+
-+ if (!test_opt(inode->i_sb, MBALLOC)) {
-+ ret = ext3_new_block_old(handle, inode, goal, pc, pb, errp);
-+ goto out;
-+ }
-+ len = 1;
-+ ret = ext3_mb_new_blocks(handle, inode, goal, &len, 0, errp);
-+out:
-+ return ret;
-+}
-+
-+
-+void ext3_free_blocks(handle_t *handle, struct inode * inode,
-+ unsigned long block, unsigned long count, int metadata)
-+{
-+ if (!test_opt(inode->i_sb, MBALLOC))
-+ ext3_free_blocks_old(handle, inode, block, count);
-+ else
-+ ext3_mb_free_blocks(handle, inode, block, count, metadata);
-+ return;
-+}
-+
-Index: linux-2.4.24/fs/ext3/super.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/super.c 2004-08-06 03:59:09.000000000 +0400
-+++ linux-2.4.24/fs/ext3/super.c 2004-08-06 03:59:09.000000000 +0400
-@@ -529,6 +529,7 @@
- kdev_t j_dev = sbi->s_journal->j_dev;
- int i;
-
-+ ext3_mb_release(sb);
- J_ASSERT(sbi->s_delete_inodes == 0);
- ext3_ext_release(sb);
- ext3_xattr_put_super(sb);
-@@ -781,6 +782,8 @@
- else if (want_numeric(value, "journal", inum))
- return 0;
- }
-+ else if (!strcmp (this_char, "mballoc"))
-+ set_opt (*mount_options, MBALLOC);
- else if (!strcmp (this_char, "noload"))
- set_opt (*mount_options, NOLOAD);
- else if (!strcmp (this_char, "data")) {
-@@ -1406,6 +1409,7 @@
- "writeback");
-
- ext3_ext_init(sb);
-+ ext3_mb_init(sb);
-
- if (test_opt(sb, PDIROPS)) {
- printk (KERN_INFO "EXT3-fs: mounted filesystem with parallel dirops\n");
-Index: linux-2.4.24/fs/ext3/Makefile
-===================================================================
---- linux-2.4.24.orig/fs/ext3/Makefile 2004-08-06 03:59:07.000000000 +0400
-+++ linux-2.4.24/fs/ext3/Makefile 2004-08-06 03:59:09.000000000 +0400
-@@ -13,7 +13,7 @@
-
- obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
- ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o \
-- xattr_trusted.o extents.o extents-in-ea.o
-+ xattr_trusted.o extents.o extents-in-ea.o mballoc.o
- export-objs += extents.o
-
- obj-m := $(O_TARGET)
-Index: linux-2.4.24/fs/ext3/balloc.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/balloc.c 2004-08-06 00:42:23.000000000 +0400
-+++ linux-2.4.24/fs/ext3/balloc.c 2004-08-06 03:59:09.000000000 +0400
-@@ -203,8 +203,7 @@
- * differentiating between a group for which we have never performed a bitmap
- * IO request, and a group for which the last bitmap read request failed.
- */
--static inline int load_block_bitmap (struct super_block * sb,
-- unsigned int block_group)
-+int load_block_bitmap (struct super_block * sb, unsigned int block_group)
- {
- int slot;
-
-@@ -253,8 +252,8 @@
- }
-
- /* Free given blocks, update quota and i_blocks field */
--void ext3_free_blocks (handle_t *handle, struct inode * inode,
-- unsigned long block, unsigned long count)
-+void ext3_free_blocks_old (handle_t *handle, struct inode * inode,
-+ unsigned long block, unsigned long count)
- {
- struct buffer_head *bitmap_bh;
- struct buffer_head *gd_bh;
-@@ -528,9 +527,9 @@
- * bitmap, and then for any free bit if that fails.
- * This function also updates quota and i_blocks field.
- */
--int ext3_new_block (handle_t *handle, struct inode * inode,
-- unsigned long goal, u32 * prealloc_count,
-- u32 * prealloc_block, int * errp)
-+int ext3_new_block_old (handle_t *handle, struct inode * inode,
-+ unsigned long goal, u32 * prealloc_count,
-+ u32 * prealloc_block, int * errp)
- {
- struct buffer_head * bh, *bhtmp;
- struct buffer_head * bh2;
-Index: linux-2.4.24/fs/ext3/namei.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/namei.c 2004-08-06 03:59:09.000000000 +0400
-+++ linux-2.4.24/fs/ext3/namei.c 2004-08-06 03:59:09.000000000 +0400
-@@ -1944,7 +1944,7 @@
- * If the create succeeds, we fill in the inode information
- * with d_instantiate().
- */
--static int ext3_create (struct inode * dir, struct dentry * dentry, int mode)
-+int ext3_create (struct inode * dir, struct dentry * dentry, int mode)
- {
- handle_t *handle;
- struct inode * inode;
-Index: linux-2.4.24/fs/ext3/inode.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/inode.c 2004-08-06 03:59:09.000000000 +0400
-+++ linux-2.4.24/fs/ext3/inode.c 2004-08-06 03:59:09.000000000 +0400
-@@ -254,7 +254,7 @@
- inode->u.ext3_i.i_prealloc_count = 0;
- inode->u.ext3_i.i_prealloc_block = 0;
- /* Writer: end */
-- ext3_free_blocks (inode, block, total);
-+ ext3_free_blocks (inode, block, total, 1);
- }
- unlock_kernel();
- #endif
-@@ -618,7 +618,7 @@
- ext3_journal_forget(handle, branch[i].bh);
- }
- for (i = 0; i < keys; i++)
-- ext3_free_blocks(handle, inode, le32_to_cpu(branch[i].key), 1);
-+ ext3_free_blocks(handle, inode, le32_to_cpu(branch[i].key), 1, 1);
- return err;
- }
-
-@@ -722,7 +722,7 @@
- if (err == -EAGAIN)
- for (i = 0; i < num; i++)
- ext3_free_blocks(handle, inode,
-- le32_to_cpu(where[i].key), 1);
-+ le32_to_cpu(where[i].key), 1, 1);
- return err;
- }
-
-@@ -1650,7 +1650,7 @@
- }
- }
-
-- ext3_free_blocks(handle, inode, block_to_free, count);
-+ ext3_free_blocks(handle, inode, block_to_free, count, 1);
- }
-
- /**
-@@ -1821,7 +1821,7 @@
- ext3_journal_test_restart(handle, inode);
- }
-
-- ext3_free_blocks(handle, inode, nr, 1);
-+ ext3_free_blocks(handle, inode, nr, 1, 1);
-
- if (parent_bh) {
- /*
-Index: linux-2.4.24/fs/ext3/extents.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/extents.c 2004-08-06 03:59:01.000000000 +0400
-+++ linux-2.4.24/fs/ext3/extents.c 2004-08-06 03:59:09.000000000 +0400
-@@ -741,7 +741,7 @@
- for (i = 0; i < depth; i++) {
- if (!ablocks[i])
- continue;
-- ext3_free_blocks(handle, tree->inode, ablocks[i], 1);
-+ ext3_free_blocks(handle, tree->inode, ablocks[i], 1, 1);
- }
- }
- kfree(ablocks);
-@@ -1385,7 +1385,7 @@
- path->p_idx->e_leaf);
- bh = sb_get_hash_table(tree->inode->i_sb, path->p_idx->e_leaf);
- ext3_forget(handle, 1, tree->inode, bh, path->p_idx->e_leaf);
-- ext3_free_blocks(handle, tree->inode, path->p_idx->e_leaf, 1);
-+ ext3_free_blocks(handle, tree->inode, path->p_idx->e_leaf, 1, 1);
- return err;
- }
-
-@@ -1842,10 +1842,12 @@
- int needed = ext3_remove_blocks_credits(tree, ex, from, to);
- handle_t *handle = ext3_journal_start(tree->inode, needed);
- struct buffer_head *bh;
-- int i;
-+ int i, metadata = 0;
-
- if (IS_ERR(handle))
- return PTR_ERR(handle);
-+ if (S_ISDIR(tree->inode->i_mode))
-+ metadata = 1;
- if (from >= ex->e_block && to == ex->e_block + ex->e_num - 1) {
- /* tail removal */
- unsigned long num, start;
-@@ -1857,7 +1859,7 @@
- bh = sb_get_hash_table(tree->inode->i_sb, start + i);
- ext3_forget(handle, 0, tree->inode, bh, start + i);
- }
-- ext3_free_blocks(handle, tree->inode, start, num);
-+ ext3_free_blocks(handle, tree->inode, start, num, metadata);
- } else if (from == ex->e_block && to <= ex->e_block + ex->e_num - 1) {
- printk("strange request: removal %lu-%lu from %u:%u\n",
- from, to, ex->e_block, ex->e_num);
-Index: linux-2.4.24/fs/ext3/xattr.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/xattr.c 2004-08-06 03:59:08.000000000 +0400
-+++ linux-2.4.24/fs/ext3/xattr.c 2004-08-06 03:59:09.000000000 +0400
-@@ -174,7 +174,7 @@
- ext3_xattr_free_block(handle_t *handle, struct inode * inode,
- unsigned long block)
- {
-- ext3_free_blocks(handle, inode, block, 1);
-+ ext3_free_blocks(handle, inode, block, 1, 1);
- inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
- }
-
-@@ -182,7 +182,7 @@
- # define ext3_xattr_quota_free(inode) \
- DQUOT_FREE_BLOCK(inode, 1)
- # define ext3_xattr_free_block(handle, inode, block) \
-- ext3_free_blocks(handle, inode, block, 1)
-+ ext3_free_blocks(handle, inode, block, 1, 1)
- #endif
-
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
-Index: linux-2.4.24/include/linux/ext3_fs.h
-===================================================================
---- linux-2.4.24.orig/include/linux/ext3_fs.h 2004-08-06 03:59:09.000000000 +0400
-+++ linux-2.4.24/include/linux/ext3_fs.h 2004-08-06 03:59:09.000000000 +0400
-@@ -343,6 +343,7 @@
- #define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */
- #define EXT3_MOUNT_EXTENTS 0x40000 /* Extents support */
- #define EXT3_MOUNT_EXTDEBUG 0x80000 /* Extents debug */
-+#define EXT3_MOUNT_MBALLOC 0x100000/* buddy allocation support */
-
- /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
- #ifndef _LINUX_EXT2_FS_H
-@@ -677,7 +678,7 @@
- extern int ext3_new_block (handle_t *, struct inode *, unsigned long,
- __u32 *, __u32 *, int *);
- extern void ext3_free_blocks (handle_t *, struct inode *, unsigned long,
-- unsigned long);
-+ unsigned long, int);
- extern unsigned long ext3_count_free_blocks (struct super_block *);
- extern void ext3_check_blocks_bitmap (struct super_block *);
- extern struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb,
-Index: linux-2.4.24/include/linux/ext3_fs_sb.h
-===================================================================
---- linux-2.4.24.orig/include/linux/ext3_fs_sb.h 2004-08-06 03:59:09.000000000 +0400
-+++ linux-2.4.24/include/linux/ext3_fs_sb.h 2004-08-06 04:01:55.000000000 +0400
-@@ -19,6 +19,7 @@
- #ifdef __KERNEL__
- #include <linux/timer.h>
- #include <linux/wait.h>
-+#include <linux/list.h>
- #endif
-
- /*
-@@ -31,6 +32,25 @@
-
- #define EXT3_DELETE_THREAD
-
-+#define EXT3_BB_MAX_BLOCKS 30
-+struct ext3_free_metadata {
-+ unsigned short group;
-+ unsigned short num;
-+ unsigned short blocks[EXT3_BB_MAX_BLOCKS];
-+ struct list_head list;
-+};
-+
-+#define EXT3_BB_MAX_ORDER 14
-+
-+struct ext3_buddy_group_blocks {
-+ unsigned long bb_bitmap;
-+ unsigned long bb_buddy;
-+ spinlock_t bb_lock;
-+ unsigned bb_counters[EXT3_BB_MAX_ORDER];
-+ struct ext3_free_metadata *bb_md_cur;
-+ unsigned long bb_tid;
-+};
-+
- /*
- * third extended-fs super-block data in memory
- */
-@@ -87,6 +107,17 @@
- wait_queue_head_t s_delete_waiter_queue;
- #endif
- u32 s_mdsnum;
-+
-+ /* for buddy allocator */
-+ struct ext3_buddy_group_blocks *s_buddy_blocks;
-+ struct inode *s_buddy;
-+ long s_blocks_reserved;
-+ spinlock_t s_reserve_lock;
-+ struct list_head s_active_transaction;
-+ struct list_head s_closed_transaction;
-+ struct list_head s_committed_transaction;
-+ spinlock_t s_md_lock;
-+ unsigned int s_last_transaction;
- };
-
- #endif /* _LINUX_EXT3_FS_SB */
-Index: linux-2.4.24/include/asm-i386/bitops.h
-===================================================================
---- linux-2.4.24.orig/include/asm-i386/bitops.h 2004-08-06 01:43:20.000000000 +0400
-+++ linux-2.4.24/include/asm-i386/bitops.h 2004-08-06 03:59:09.000000000 +0400
-@@ -352,6 +352,67 @@
- }
-
- /**
-+ * find_first_bit - find the first set bit in a memory region
-+ * @addr: The address to start the search at
-+ * @size: The maximum size to search
-+ *
-+ * Returns the bit-number of the first set bit, not the number of the byte
-+ * containing a bit.
-+ */
-+static __inline__ int find_first_bit(const unsigned long *addr, unsigned size)
-+{
-+ int d0, d1;
-+ int res;
-+
-+ /* This looks at memory. Mark it volatile to tell gcc not to move it around */
-+ __asm__ __volatile__(
-+ "xorl %%eax,%%eax\n\t"
-+ "repe; scasl\n\t"
-+ "jz 1f\n\t"
-+ "leal -4(%%edi),%%edi\n\t"
-+ "bsfl (%%edi),%%eax\n"
-+ "1:\tsubl %%ebx,%%edi\n\t"
-+ "shll $3,%%edi\n\t"
-+ "addl %%edi,%%eax"
-+ :"=a" (res), "=&c" (d0), "=&D" (d1)
-+ :"1" ((size + 31) >> 5), "2" (addr), "b" (addr) : "memory");
-+ return res;
-+}
-+
-+/**
-+ * find_next_bit - find the first set bit in a memory region
-+ * @addr: The address to base the search on
-+ * @offset: The bitnumber to start searching at
-+ * @size: The maximum size to search
-+ */
-+static __inline__ int find_next_bit(const unsigned long *addr, int size, int offset)
-+{
-+ const unsigned long *p = addr + (offset >> 5);
-+ int set = 0, bit = offset & 31, res;
-+
-+ if (bit) {
-+ /*
-+ * Look for nonzero in the first 32 bits:
-+ */
-+ __asm__("bsfl %1,%0\n\t"
-+ "jne 1f\n\t"
-+ "movl $32, %0\n"
-+ "1:"
-+ : "=r" (set)
-+ : "r" (*p >> bit));
-+ if (set < (32 - bit))
-+ return set + offset;
-+ set = 32 - bit;
-+ p++;
-+ }
-+ /*
-+ * No set bit yet, search remaining full words for a bit
-+ */
-+ res = find_first_bit (p, size - 32 * (p - addr));
-+ return (offset + set + res);
-+}
-+
-+/**
- * hweightN - returns the hamming weight of a N-bit word
- * @x: the word to weigh
- *
+++ /dev/null
-Index: linux-2.4.24/fs/ext3/namei.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/namei.c 2004-09-23 13:10:48.181661672 +0400
-+++ linux-2.4.24/fs/ext3/namei.c 2004-09-23 13:10:48.274647536 +0400
-@@ -1099,6 +1099,23 @@
- inode = NULL;
- if (bh) {
- unsigned long ino = le32_to_cpu(de->inode);
-+ unsigned type = de->file_type;
-+ __u32 *mds;
-+ mds = (__u32 *)((char *) de + EXT3_DIR_REC_LEN(de->name_len));
-+ if ((type & 128) && EXT3_HAS_INCOMPAT_FEATURE(dir->i_sb,
-+ EXT3_FEATURE_INCOMPAT_MDSNUM) &&
-+ mds[0] != EXT3_SB(dir->i_sb)->s_mdsnum) {
-+ struct ext3_super_block *es;
-+ es = EXT3_SB(dir->i_sb)->s_es;
-+ ext3_unlock_htree(dir, lock);
-+ brelse (bh);
-+ dentry->d_flags |= DCACHE_CROSS_REF;
-+ dentry->d_generation = mds[1];
-+ dentry->d_mdsnum = mds[0];
-+ dentry->d_inum = ino;
-+ d_add(dentry, NULL);
-+ return NULL;
-+ }
- ext3_unlock_htree(dir, lock);
- brelse (bh);
- inode = iget(dir->i_sb, ino);
-@@ -1138,7 +1155,7 @@
- while (count--) {
- struct ext3_dir_entry_2 *de =
- (struct ext3_dir_entry_2 *) (from + map->offs);
-- rec_len = EXT3_DIR_REC_LEN(de->name_len);
-+ rec_len = EXT3_DIR_REC_LEN_DE(de);
- memcpy (to, de, rec_len);
- ((struct ext3_dir_entry_2 *)to)->rec_len = cpu_to_le16(rec_len);
- de->inode = 0;
-@@ -1159,7 +1176,7 @@
- next = (struct ext3_dir_entry_2 *) ((char *) de +
- le16_to_cpu(de->rec_len));
- if (de->inode && de->name_len) {
-- rec_len = EXT3_DIR_REC_LEN(de->name_len);
-+ rec_len = EXT3_DIR_REC_LEN_DE(de);
- if (de > to)
- memmove(to, de, rec_len);
- to->rec_len = cpu_to_le16(rec_len);
-@@ -1275,6 +1292,7 @@
- struct buffer_head * bh)
- {
- struct inode *dir = dentry->d_parent->d_inode;
-+ struct super_block *sb = dir->i_sb;
- const char *name = dentry->d_name.name;
- int namelen = dentry->d_name.len;
- unsigned long offset = 0;
-@@ -1283,6 +1301,10 @@
- char *top;
-
- reclen = EXT3_DIR_REC_LEN(namelen);
-+ if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_MDSNUM)
-+ && (dentry->d_flags & DCACHE_CROSS_REF)
-+ && (dentry->d_mdsnum != EXT3_SB(sb)->s_mdsnum))
-+ reclen += 8; /* we need space to store mds num */
- if (!de) {
- de = (struct ext3_dir_entry_2 *)bh->b_data;
- top = bh->b_data + dir->i_sb->s_blocksize - reclen;
-@@ -1296,7 +1318,7 @@
- brelse (bh);
- return -EEXIST;
- }
-- nlen = EXT3_DIR_REC_LEN(de->name_len);
-+ nlen = EXT3_DIR_REC_LEN_DE(de);
- rlen = le16_to_cpu(de->rec_len);
- if ((de->inode? rlen - nlen: rlen) >= reclen)
- break;
-@@ -1315,7 +1337,7 @@
- }
-
- /* By now the buffer is marked for journaling */
-- nlen = EXT3_DIR_REC_LEN(de->name_len);
-+ nlen = EXT3_DIR_REC_LEN_DE(de);
- rlen = le16_to_cpu(de->rec_len);
- if (de->inode) {
- struct ext3_dir_entry_2 *de1 =
-@@ -1327,8 +1349,20 @@
- de->file_type = EXT3_FT_UNKNOWN;
- if (inode) {
- de->inode = cpu_to_le32(inode->i_ino);
-- ext3_set_de_type(dir->i_sb, de, inode->i_mode);
-- } else
-+ ext3_set_de_type(sb, de, inode->i_mode);
-+ } else if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_MDSNUM)
-+ && (dentry->d_flags & DCACHE_CROSS_REF)) {
-+ if (dentry->d_mdsnum != EXT3_SB(sb)->s_mdsnum) {
-+ __u32 *mds;
-+ mds = (__u32 *)((char *)de + EXT3_DIR_REC_LEN(namelen));
-+ mds[0] = cpu_to_le32(dentry->d_mdsnum);
-+ mds[1] = cpu_to_le32(dentry->d_generation);
-+ de->inode = cpu_to_le32(dentry->d_inum);
-+ de->file_type = 128;
-+ } else {
-+ de->inode = cpu_to_le32(dentry->d_inum);
-+ }
-+ } else
- de->inode = 0;
- de->name_len = namelen;
- memcpy (de->name, name, namelen);
-@@ -2662,6 +2696,79 @@
- }
-
- /*
-+ * caller has to make sure directory is protected
-+ */
-+int ext3_add_dir_entry(struct dentry *dentry)
-+{
-+ struct inode *dir = dentry->d_parent->d_inode;
-+ handle_t *handle;
-+ int err;
-+
-+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS);
-+ if (IS_ERR(handle)) {
-+ return PTR_ERR(handle);
-+ }
-+
-+ if (IS_SYNC(dir))
-+ handle->h_sync = 1;
-+
-+ err = ext3_add_entry(handle, dentry, NULL);
-+ ext3_journal_stop(handle, dir);
-+ return err;
-+}
-+
-+/*
-+ * caller has to make sure directory is protected
-+ */
-+int ext3_del_dir_entry(struct dentry *dentry)
-+{
-+ struct inode * inode;
-+ struct inode * dir = dentry->d_parent->d_inode;
-+ struct buffer_head * bh;
-+ struct ext3_dir_entry_2 * de;
-+ handle_t *handle;
-+ void *lock;
-+ int retval;
-+
-+ handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
-+ if (IS_ERR(handle)) {
-+ return PTR_ERR(handle);
-+ }
-+
-+ if (IS_SYNC(dir))
-+ handle->h_sync = 1;
-+
-+ retval = -ENOENT;
-+ bh = ext3_find_entry (dentry, &de, 1, &lock);
-+ if (!bh)
-+ goto end_unlink;
-+
-+ inode = dentry->d_inode;
-+ if (inode)
-+ DQUOT_INIT(inode);
-+
-+ retval = ext3_delete_entry(handle, dir, de, bh);
-+ ext3_unlock_htree(dir, lock);
-+ if (retval)
-+ goto end_unlink;
-+ dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-+ ext3_update_dx_flag(dir);
-+ if (inode) {
-+ inode->i_ctime = dir->i_ctime;
-+ ext3_mark_inode_dirty(handle, inode);
-+ if (S_ISDIR(inode->i_mode))
-+ dir->i_nlink--;
-+ }
-+ ext3_mark_inode_dirty(handle, dir);
-+ retval = 0;
-+
-+end_unlink:
-+ ext3_journal_stop(handle, dir);
-+ brelse (bh);
-+ return retval;
-+}
-+/*
- * directories can handle most operations...
- */
- struct inode_operations ext3_dir_inode_operations = {
-Index: linux-2.4.24/fs/ext3/dir.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/dir.c 2004-09-23 13:10:45.649046688 +0400
-+++ linux-2.4.24/fs/ext3/dir.c 2004-09-23 13:10:48.275647384 +0400
-@@ -42,6 +42,9 @@
-
- static unsigned char get_dtype(struct super_block *sb, int filetype)
- {
-+ if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_MDSNUM))
-+ return DT_UNKNOWN;
-+
- if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_FILETYPE) ||
- (filetype >= EXT3_FT_MAX))
- return DT_UNKNOWN;
-@@ -67,8 +70,10 @@
- else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
- error_msg = "directory entry across blocks";
- else if (le32_to_cpu(de->inode) >
-- le32_to_cpu(dir->i_sb->u.ext3_sb.s_es->s_inodes_count))
-- error_msg = "inode out of bounds";
-+ le32_to_cpu(dir->i_sb->u.ext3_sb.s_es->s_inodes_count)) {
-+ if (de->file_type != 128)
-+ error_msg = "inode out of bounds";
-+ }
-
- if (error_msg != NULL)
- ext3_error (dir->i_sb, function,
-Index: linux-2.4.24/fs/ext3/ext3-exports.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/ext3-exports.c 2004-09-23 13:10:46.365937704 +0400
-+++ linux-2.4.24/fs/ext3/ext3-exports.c 2004-09-23 13:10:48.275647384 +0400
-@@ -26,3 +26,10 @@
- EXPORT_SYMBOL(ext3_decode_error);
- EXPORT_SYMBOL(__ext3_std_error);
-
-+int ext3_add_dir_entry (struct dentry *dentry);
-+EXPORT_SYMBOL(ext3_add_dir_entry);
-+int ext3_del_dir_entry(struct dentry *dentry);
-+EXPORT_SYMBOL(ext3_del_dir_entry);
-+
-+
-+
-Index: linux-2.4.24/include/linux/ext3_fs.h
-===================================================================
---- linux-2.4.24.orig/include/linux/ext3_fs.h 2004-09-23 13:10:48.188660608 +0400
-+++ linux-2.4.24/include/linux/ext3_fs.h 2004-09-23 13:17:40.703948752 +0400
-@@ -446,7 +446,8 @@
- __u8 s_def_hash_version; /* Default hash version to use */
- __u8 s_reserved_char_pad;
- __u16 s_reserved_word_pad;
-- __u32 s_reserved[192]; /* Padding to the end of the block */
-+ __u32 s_mdsnum;
-+ __u32 s_reserved[191]; /* Padding to the end of the block */
- };
-
- #ifdef __KERNEL__
-@@ -519,11 +520,13 @@
- #define EXT3_FEATURE_INCOMPAT_FILETYPE 0x0002
- #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
- #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
-+#define EXT3_FEATURE_INCOMPAT_MDSNUM 0x0020 /* direntry has mdsnum */
- #define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
-
- #define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
- #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \
- EXT3_FEATURE_INCOMPAT_RECOVER| \
-+ EXT3_FEATURE_INCOMPAT_MDSNUM| \
- EXT3_FEATURE_INCOMPAT_EXTENTS)
- #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
- EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
-@@ -585,6 +588,9 @@
- #define EXT3_DIR_ROUND (EXT3_DIR_PAD - 1)
- #define EXT3_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT3_DIR_ROUND) & \
- ~EXT3_DIR_ROUND)
-+#define EXT3_DIR_REC_LEN_DE(de) (EXT3_DIR_REC_LEN((de)->name_len) + \
-+ (((de)->file_type & 128) ? 8 : 0))
-+
- /*
- * Hash Tree Directory indexing
- * (c) Daniel Phillips, 2001
-Index: linux-2.4.24/include/linux/ext3_fs_sb.h
-===================================================================
---- linux-2.4.24.orig/include/linux/ext3_fs_sb.h 2004-09-23 13:10:46.069982696 +0400
-+++ linux-2.4.24/include/linux/ext3_fs_sb.h 2004-09-23 13:11:21.026668472 +0400
-@@ -86,6 +86,7 @@
- wait_queue_head_t s_delete_thread_queue;
- wait_queue_head_t s_delete_waiter_queue;
- #endif
-+ u32 s_mdsnum;
- };
-
- #endif /* _LINUX_EXT3_FS_SB */
-Index: linux-2.4.24/include/linux/dcache.h
-===================================================================
---- linux-2.4.24.orig/include/linux/dcache.h 2004-09-23 13:10:46.153969928 +0400
-+++ linux-2.4.24/include/linux/dcache.h 2004-09-23 13:11:06.451884176 +0400
-@@ -120,6 +120,9 @@
- atomic_t d_count;
- unsigned int d_flags;
- struct inode * d_inode; /* Where the name belongs to - NULL is negative */
-+ unsigned d_inum; /* for cross-fs references (Lustre) */
-+ unsigned d_mdsnum; /* for cross-fs references (Lustre) */
-+ unsigned d_generation; /* for cross-fs references (Lustre) */
- struct dentry * d_parent; /* parent directory */
- struct list_head d_hash; /* lookup hash list */
- struct list_head d_lru; /* d_count = 0 LRU list */
-@@ -193,6 +196,7 @@
- */
- #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */
- #define DCACHE_LUSTRE_INVALID 0x0010 /* Lustre invalidated */
-+#define DCACHE_CROSS_REF 0x0020 /* entry points to inode on another MDS */
-
- extern spinlock_t dcache_lock;
-
+++ /dev/null
---- ./fs/ext3/namei.c.orig 2004-08-19 12:53:21.000000000 +0800
-+++ ./fs/ext3/namei.c 2004-08-19 12:44:18.000000000 +0800
-@@ -1541,11 +1541,16 @@
- static inline void ext3_inc_count(handle_t *handle, struct inode *inode)
- {
- inode->i_nlink++;
-+ if (is_dx(inode) && inode->i_nlink > 1) {
-+ if (inode->i_nlink >= 65000) /* limit is 16-bit i_links_count */
-+ inode->i_nlink = 1;
-+ }
- }
-
- static inline void ext3_dec_count(handle_t *handle, struct inode *inode)
- {
-- inode->i_nlink--;
-+ if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2)
-+ inode->i_nlink--;
- }
-
- static int ext3_add_nondir(handle_t *handle,
-@@ -1646,7 +1651,7 @@
- struct ext3_dir_entry_2 * de;
- int err;
-
-- if (dir->i_nlink >= EXT3_LINK_MAX)
-+ if (EXT3_DIR_LINK_MAXED(dir))
- return -EMLINK;
-
- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-@@ -1668,7 +1673,7 @@
- inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
- dir_block = ext3_bread (handle, inode, 0, 1, &err);
- if (!dir_block) {
-- inode->i_nlink--; /* is this nlink == 0? */
-+ ext3_dec_count(handle, inode); /* is this nlink == 0? */
- ext3_mark_inode_dirty(handle, inode);
- iput (inode);
- goto out_stop;
-@@ -1700,7 +1705,7 @@
- iput (inode);
- goto out_stop;
- }
-- dir->i_nlink++;
-+ ext3_inc_count(handle, dir);
- ext3_update_dx_flag(dir);
- ext3_mark_inode_dirty(handle, dir);
- d_instantiate(dentry, inode);
-@@ -1761,10 +1766,11 @@
- }
- de = (struct ext3_dir_entry_2 *) bh->b_data;
- }
-- if (!ext3_check_dir_entry ("empty_dir", inode, de, bh,
-- offset)) {
-- brelse (bh);
-- return 1;
-+ if (!ext3_check_dir_entry("empty_dir", inode, de, bh, offset)) {
-+ /* On error skip the de and offset to the next block. */
-+ de = (void *)(bh->b_data + sb->s_blocksize);
-+ offset = (offset | (sb->s_blocksize - 1)) + 1;
-+ continue;
- }
- if (le32_to_cpu(de->inode)) {
- brelse (bh);
-@@ -1957,14 +1963,14 @@
- retval = ext3_delete_entry(handle, dir, de, bh);
- if (retval)
- goto end_rmdir;
-- if (inode->i_nlink != 2)
-- ext3_warning (inode->i_sb, "ext3_rmdir",
-- "empty directory has nlink!=2 (%d)",
-- inode->i_nlink);
-+ if (!EXT3_DIR_LINK_EMPTY(inode))
-+ ext3_warning(inode->i_sb, __FUNCTION__,
-+ "empty directory has too many links (%d)",
-+ inode->i_nlink);
- inode->i_version = ++event;
- inode->i_nlink = 0;
- ext3_orphan_add(handle, inode);
-- dir->i_nlink--;
-+ ext3_dec_count(handle, dir);
- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
- ext3_mark_inode_dirty(handle, inode);
- ext3_update_dx_flag(dir);
-@@ -2046,7 +2052,7 @@
- dir->i_ctime = dir->i_mtime = CURRENT_TIME;
- ext3_update_dx_flag(dir);
- ext3_mark_inode_dirty(handle, dir);
-- inode->i_nlink--;
-+ ext3_dec_count(handle, inode);
- if (!inode->i_nlink) {
- ext3_try_to_delay_deletion(inode);
- ext3_orphan_add(handle, inode);
-@@ -2140,9 +2146,8 @@
- if (S_ISDIR(inode->i_mode))
- return -EPERM;
-
-- if (inode->i_nlink >= EXT3_LINK_MAX) {
-+ if (EXT3_DIR_LINK_MAXED(inode))
- return -EMLINK;
-- }
-
- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
- EXT3_INDEX_EXTRA_TRANS_BLOCKS);
-@@ -2226,8 +2231,8 @@
- if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino)
- goto end_rename;
- retval = -EMLINK;
-- if (!new_inode && new_dir!=old_dir &&
-- new_dir->i_nlink >= EXT3_LINK_MAX)
-+ if (!new_inode && new_dir != old_dir &&
-+ EXT3_DIR_LINK_MAXED(new_dir))
- goto end_rename;
- }
- if (!new_bh) {
-@@ -2285,7 +2290,7 @@
- }
-
- if (new_inode) {
-- new_inode->i_nlink--;
-+ ext3_dec_count(handle, new_inode);
- new_inode->i_ctime = CURRENT_TIME;
- }
- old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
-@@ -2296,11 +2301,11 @@
- PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino);
- BUFFER_TRACE(dir_bh, "call ext3_journal_dirty_metadata");
- ext3_journal_dirty_metadata(handle, dir_bh);
-- old_dir->i_nlink--;
-+ ext3_dec_count(handle, old_dir);
- if (new_inode) {
-- new_inode->i_nlink--;
-+ ext3_dec_count(handle, new_inode);
- } else {
-- new_dir->i_nlink++;
-+ ext3_inc_count(handle, new_dir);
- ext3_update_dx_flag(new_dir);
- ext3_mark_inode_dirty(handle, new_dir);
- }
---- ./include/linux/ext3_fs.h.orig 2004-08-19 12:53:52.000000000 +0800
-+++ ./include/linux/ext3_fs.h 2004-08-19 11:06:33.000000000 +0800
-@@ -42,7 +42,7 @@
- /*
- * Always enable hashed directories
- */
--#define CONFIG_EXT3_INDEX
-+#define CONFIG_EXT3_INDEX 1
-
- /*
- * Debug code
-@@ -581,14 +581,15 @@
- */
-
- #ifdef CONFIG_EXT3_INDEX
-- #define is_dx(dir) (EXT3_HAS_COMPAT_FEATURE(dir->i_sb, \
-- EXT3_FEATURE_COMPAT_DIR_INDEX) && \
-+#define is_dx(dir) (EXT3_HAS_COMPAT_FEATURE(dir->i_sb, \
-+ EXT3_FEATURE_COMPAT_DIR_INDEX) && \
- (EXT3_I(dir)->i_flags & EXT3_INDEX_FL))
--#define EXT3_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT3_LINK_MAX)
--#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1)
-+#define EXT3_DIR_LINK_MAXED(dir) (!is_dx(dir) && (dir)->i_nlink >=EXT3_LINK_MAX)
-+#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || \
-+ (is_dx(dir) && (dir)->i_nlink == 1))
- #else
- #define is_dx(dir) 0
--#define EXT3_DIR_LINK_MAX(dir) ((dir)->i_nlink >= EXT3_LINK_MAX)
-+#define EXT3_DIR_LINK_MAXED(dir) ((dir)->i_nlink >= EXT3_LINK_MAX)
- #define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2)
- #endif
-
+++ /dev/null
- fs/ext3/super.c | 1 -
- 1 files changed, 1 deletion(-)
-
---- linux-2.4.18-chaos/fs/ext3/super.c~ext3-no-write-super-chaos 2003-08-24 21:34:53.000000000 +0400
-+++ linux-2.4.18-chaos-alexey/fs/ext3/super.c 2003-08-24 21:40:47.000000000 +0400
-@@ -1818,7 +1818,6 @@ void ext3_write_super (struct super_bloc
- if (down_trylock(&sb->s_lock) == 0)
- BUG();
- sb->s_dirt = 0;
-- log_start_commit(EXT3_SB(sb)->s_journal, NULL);
- }
-
- static int ext3_sync_fs(struct super_block *sb)
-
-_
+++ /dev/null
- fs/ext3/ialloc.c | 47 ++++++++++++++++++++++-
- fs/ext3/inode.c | 96 +++++++++++++++++++++++++++++++++++++-----------
- include/linux/ext3_fs.h | 2 +
- 3 files changed, 121 insertions(+), 24 deletions(-)
-
---- linux-2.4.20/fs/ext3/ialloc.c~ext3-noread-2.4.20 2003-05-16 12:21:39.000000000 +0800
-+++ linux-2.4.20-root/fs/ext3/ialloc.c 2003-05-16 12:21:46.000000000 +0800
-@@ -289,6 +289,37 @@ error_return:
- }
-
- /*
-+ * @block_group: block group of inode
-+ * @offset: relative offset of inode within @block_group
-+ *
-+ * Check whether any of the inodes in this disk block are in use.
-+ *
-+ * Caller must be holding superblock lock (group/bitmap read lock in future).
-+ */
-+int ext3_itable_block_used(struct super_block *sb, unsigned int block_group,
-+ int offset)
-+{
-+ int bitmap_nr = load_inode_bitmap(sb, block_group);
-+ int inodes_per_block;
-+ unsigned long inum, iend;
-+ struct buffer_head *ibitmap;
-+
-+ if (bitmap_nr < 0)
-+ return 1;
-+
-+ inodes_per_block = sb->s_blocksize / EXT3_SB(sb)->s_inode_size;
-+ inum = offset & ~(inodes_per_block - 1);
-+ iend = inum + inodes_per_block;
-+ ibitmap = EXT3_SB(sb)->s_inode_bitmap[bitmap_nr];
-+ for (; inum < iend; inum++) {
-+ if (inum != offset && ext3_test_bit(inum, ibitmap->b_data))
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+/*
- * There are two policies for allocating an inode. If the new inode is
- * a directory, then a forward search is made for a block group with both
- * free space and a low directory-to-inode ratio; if that fails, then of
-@@ -310,6 +341,7 @@ struct inode * ext3_new_inode (handle_t
- struct ext3_group_desc * gdp;
- struct ext3_group_desc * tmp;
- struct ext3_super_block * es;
-+ struct ext3_iloc iloc;
- int err = 0;
-
- /* Cannot create files in a deleted directory */
-@@ -510,8 +542,19 @@ repeat:
- inode->i_generation = sb->u.ext3_sb.s_next_generation++;
-
- inode->u.ext3_i.i_state = EXT3_STATE_NEW;
-- err = ext3_mark_inode_dirty(handle, inode);
-- if (err) goto fail;
-+ err = ext3_get_inode_loc_new(inode, &iloc, 1);
-+ if (err) goto fail;
-+ BUFFER_TRACE(iloc->bh, "get_write_access");
-+ err = ext3_journal_get_write_access(handle, iloc.bh);
-+ if (err) {
-+ brelse(iloc.bh);
-+ iloc.bh = NULL;
-+ goto fail;
-+ }
-+ err = ext3_mark_iloc_dirty(handle, inode, &iloc);
-+ if (err) goto fail;
-+
-+
-
- unlock_super (sb);
- if(DQUOT_ALLOC_INODE(inode)) {
---- linux-2.4.20/fs/ext3/inode.c~ext3-noread-2.4.20 2003-05-16 12:21:41.000000000 +0800
-+++ linux-2.4.20-root/fs/ext3/inode.c 2003-05-16 12:22:15.000000000 +0800
-@@ -2013,14 +2013,19 @@ out_stop:
- ext3_journal_stop(handle, inode);
- }
-
--/*
-- * ext3_get_inode_loc returns with an extra refcount against the
-- * inode's underlying buffer_head on success.
-- */
--
--int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc)
-+#define NUM_INODE_PREREAD 16
-+
-+/*
-+ * ext3_get_inode_loc returns with an extra refcount against the inode's
-+ * underlying buffer_head on success. If this is for a new inode allocation
-+ * (new is non-zero) then we may be able to optimize away the read if there
-+ * are no other in-use inodes in this inode table block. If we need to do
-+ * a read, then read in a whole chunk of blocks to avoid blocking again soon
-+ * if we are doing lots of creates/updates.
-+ */
-+int ext3_get_inode_loc_new(struct inode *inode, struct ext3_iloc *iloc, int new)
- {
-- struct buffer_head *bh = 0;
-+ struct buffer_head *bh[NUM_INODE_PREREAD];
- unsigned long block;
- unsigned long block_group;
- unsigned long group_desc;
-@@ -2045,31 +2050,73 @@ int ext3_get_inode_loc (struct inode *in
- }
- group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(inode->i_sb);
- desc = block_group & (EXT3_DESC_PER_BLOCK(inode->i_sb) - 1);
-- bh = inode->i_sb->u.ext3_sb.s_group_desc[group_desc];
-- if (!bh) {
-+ if (!(inode->i_sb->u.ext3_sb.s_group_desc[group_desc])) {
- ext3_error (inode->i_sb, "ext3_get_inode_loc",
- "Descriptor not loaded");
- goto bad_inode;
- }
-
-- gdp = (struct ext3_group_desc *) bh->b_data;
-+ gdp = (struct ext3_group_desc *)(inode->i_sb->u.ext3_sb.s_group_desc[group_desc]->b_data);
- /*
- * Figure out the offset within the block group inode table
- */
-- offset = ((inode->i_ino - 1) % EXT3_INODES_PER_GROUP(inode->i_sb)) *
-- EXT3_INODE_SIZE(inode->i_sb);
-+ offset = ((inode->i_ino - 1) % EXT3_INODES_PER_GROUP(inode->i_sb));
-+
- block = le32_to_cpu(gdp[desc].bg_inode_table) +
-- (offset >> EXT3_BLOCK_SIZE_BITS(inode->i_sb));
-- if (!(bh = sb_bread(inode->i_sb, block))) {
-- ext3_error (inode->i_sb, "ext3_get_inode_loc",
-- "unable to read inode block - "
-- "inode=%lu, block=%lu", inode->i_ino, block);
-- goto bad_inode;
-- }
-- offset &= (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
-+ (offset * EXT3_INODE_SIZE(inode->i_sb) >> EXT3_BLOCK_SIZE_BITS(inode->i_sb));
-
-- iloc->bh = bh;
-- iloc->raw_inode = (struct ext3_inode *) (bh->b_data + offset);
-+ bh[0] = sb_getblk(inode->i_sb, block);
-+ if (buffer_uptodate(bh[0]))
-+ goto done;
-+
-+ /* If we don't really need to read this block, and it isn't already
-+ * in memory, then we just zero it out. Otherwise, we keep the
-+ * current block contents (deleted inode data) for posterity.
-+ */
-+ if (new && !ext3_itable_block_used(inode->i_sb, block_group, offset)) {
-+ lock_buffer(bh[0]);
-+ memset(bh[0]->b_data, 0, bh[0]->b_size);
-+ mark_buffer_uptodate(bh[0], 1);
-+ unlock_buffer(bh[0]);
-+ } else {
-+ unsigned long block_end, itable_end;
-+ int count = 1;
-+
-+ itable_end = le32_to_cpu(gdp[desc].bg_inode_table) +
-+ inode->i_sb->u.ext3_sb.s_itb_per_group;
-+ block_end = block + NUM_INODE_PREREAD;
-+ if (block_end > itable_end)
-+ block_end = itable_end;
-+
-+ for (++block; block < block_end; block++) {
-+ bh[count] = sb_getblk(inode->i_sb, block);
-+ if (count && (buffer_uptodate(bh[count]) ||
-+ buffer_locked(bh[count]))) {
-+ __brelse(bh[count]);
-+ } else
-+ count++;
-+ }
-+
-+ ll_rw_block(READ, count, bh);
-+
-+ /* Release all but the block we actually need (bh[0]) */
-+ while (--count > 0)
-+ __brelse(bh[count]);
-+
-+ wait_on_buffer(bh[0]);
-+ if (!buffer_uptodate(bh[0])) {
-+ ext3_error(inode->i_sb, __FUNCTION__,
-+ "unable to read inode block - "
-+ "inode=%lu, block=%lu", inode->i_ino,
-+ bh[0]->b_blocknr);
-+ goto bad_inode;
-+ }
-+ }
-+done:
-+ offset = (offset * EXT3_INODE_SIZE(inode->i_sb)) & (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
-+
-+ iloc->bh = bh[0];
-+ iloc->raw_inode = (struct ext3_inode *)(bh[0]->b_data + offset);
- iloc->block_group = block_group;
-
- return 0;
-@@ -2078,6 +2125,11 @@ int ext3_get_inode_loc (struct inode *in
- return -EIO;
- }
-
-+int ext3_get_inode_loc(struct inode *inode, struct ext3_iloc *iloc)
-+{
-+ return ext3_get_inode_loc_new(inode, iloc, 0);
-+}
-+
- void ext3_read_inode(struct inode * inode)
- {
- struct ext3_iloc iloc;
---- linux-2.4.20/include/linux/ext3_fs.h~ext3-noread-2.4.20 2003-05-16 12:21:39.000000000 +0800
-+++ linux-2.4.20-root/include/linux/ext3_fs.h 2003-05-16 12:21:46.000000000 +0800
-@@ -683,6 +683,8 @@ extern int ext3_forget(handle_t *, int,
- extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
- extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
-
-+extern int ext3_itable_block_used(struct super_block *sb, unsigned int, int);
-+extern int ext3_get_inode_loc_new(struct inode *, struct ext3_iloc *, int);
- extern int ext3_get_inode_loc (struct inode *, struct ext3_iloc *);
- extern void ext3_read_inode (struct inode *);
- extern void ext3_write_inode (struct inode *, int);
-
-_
+++ /dev/null
- fs/ext3/namei.c | 15 +++++++--------
- fs/ext3/namei.c.orig | 21 +++++++++++++++------
- fs/ext3/super.c | 1 +
- include/linux/ext3_fs_sb.h | 1 +
- include/linux/ext3_fs_sb.h.orig | 2 ++
- 5 files changed, 26 insertions(+), 14 deletions(-)
-
---- linux-2.4.22-ac1/fs/ext3/namei.c~ext3-orphan_lock-2.4.22-rh 2003-09-26 00:24:09.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext3/namei.c 2003-09-26 00:26:36.000000000 +0400
-@@ -1748,8 +1748,8 @@ int ext3_orphan_add(handle_t *handle, st
- struct super_block *sb = inode->i_sb;
- struct ext3_iloc iloc;
- int err = 0, rc;
--
-- lock_super(sb);
-+
-+ down(&EXT3_SB(sb)->s_orphan_lock);
- if (!list_empty(&EXT3_I(inode)->i_orphan))
- goto out_unlock;
-
-@@ -1797,7 +1797,7 @@ int ext3_orphan_add(handle_t *handle, st
- jbd_debug(4, "orphan inode %ld will point to %d\n",
- inode->i_ino, NEXT_ORPHAN(inode));
- out_unlock:
-- unlock_super(sb);
-+ up(&EXT3_SB(sb)->s_orphan_lock);
- ext3_std_error(inode->i_sb, err);
- return err;
- }
-@@ -1810,20 +1810,19 @@ int ext3_orphan_del(handle_t *handle, st
- {
- struct list_head *prev;
- struct ext3_inode_info *ei = EXT3_I(inode);
-- struct ext3_sb_info *sbi;
-+ struct ext3_sb_info *sbi = EXT3_SB(inode->i_sb);
- unsigned long ino_next;
- struct ext3_iloc iloc;
- int err = 0;
-
-- lock_super(inode->i_sb);
-+ down(&sbi->s_orphan_lock);
- if (list_empty(&ei->i_orphan)) {
-- unlock_super(inode->i_sb);
-+ up(&sbi->s_orphan_lock);
- return 0;
- }
-
- ino_next = NEXT_ORPHAN(inode);
- prev = ei->i_orphan.prev;
-- sbi = EXT3_SB(inode->i_sb);
-
- jbd_debug(4, "remove inode %lu from orphan list\n", inode->i_ino);
-
-@@ -1872,7 +1871,7 @@ int ext3_orphan_del(handle_t *handle, st
- out_err:
- ext3_std_error(inode->i_sb, err);
- out:
-- unlock_super(inode->i_sb);
-+ up(&sbi->s_orphan_lock);
- return err;
-
- out_brelse:
---- linux-2.4.22-ac1/fs/ext3/super.c~ext3-orphan_lock-2.4.22-rh 2003-09-26 00:24:09.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/fs/ext3/super.c 2003-09-26 00:25:22.000000000 +0400
-@@ -1164,6 +1164,7 @@ struct super_block * ext3_read_super (st
- sb->s_op = &ext3_sops;
- sb->dq_op = &ext3_qops;
- INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
-+ sema_init(&sbi->s_orphan_lock, 1);
-
- sb->s_root = 0;
-
---- linux-2.4.22-ac1/include/linux/ext3_fs_sb.h~ext3-orphan_lock-2.4.22-rh 2003-09-26 00:24:08.000000000 +0400
-+++ linux-2.4.22-ac1-alexey/include/linux/ext3_fs_sb.h 2003-09-26 00:25:22.000000000 +0400
-@@ -72,6 +72,7 @@ struct ext3_sb_info {
- struct inode * s_journal_inode;
- struct journal_s * s_journal;
- struct list_head s_orphan;
-+ struct semaphore s_orphan_lock;
- unsigned long s_commit_interval;
- struct block_device *journal_bdev;
- #ifdef CONFIG_JBD_DEBUG
+++ /dev/null
- fs/ext3/ialloc.c | 3
- fs/ext3/inode.c | 3
- fs/ext3/namei.c | 582 +++++++++++++++++++++++++++++++++++++---------
- fs/ext3/super.c | 14 +
- include/linux/ext3_fs.h | 1
- include/linux/ext3_fs_i.h | 6
- 6 files changed, 500 insertions(+), 109 deletions(-)
-
-Index: lum/fs/ext3/namei.c
-===================================================================
---- lum.orig/fs/ext3/namei.c 2004-06-03 16:32:28.000000000 -0400
-+++ lum/fs/ext3/namei.c 2004-06-03 16:45:45.000000000 -0400
-@@ -51,6 +51,9 @@
- {
- struct buffer_head *bh;
-
-+ /* with parallel dir operations all appends
-+ * have to be serialized -bzzz */
-+ down(&EXT3_I(inode)->i_append_sem);
- *block = inode->i_size >> inode->i_sb->s_blocksize_bits;
-
- if ((bh = ext3_bread(handle, inode, *block, 1, err))) {
-@@ -58,6 +61,8 @@
- EXT3_I(inode)->i_disksize = inode->i_size;
- ext3_journal_get_write_access(handle,bh);
- }
-+ up(&EXT3_I(inode)->i_append_sem);
-+
- return bh;
- }
-
-@@ -134,6 +139,8 @@
- struct buffer_head *bh;
- struct dx_entry *entries;
- struct dx_entry *at;
-+ unsigned long leaf;
-+ unsigned int curidx;
- };
-
- struct dx_map_entry
-@@ -142,6 +149,30 @@
- u32 offs;
- };
-
-+/* FIXME: this should be reworked using bb_spin_lock
-+ * introduced in -mm tree
-+ */
-+#define BH_DXLock 25
-+
-+static inline void dx_lock_bh(struct buffer_head volatile *bh)
-+{
-+#ifdef CONFIG_SMP
-+ while (test_and_set_bit(BH_DXLock, &bh->b_state)) {
-+ while (test_bit(BH_DXLock, &bh->b_state))
-+ cpu_relax();
-+ }
-+#endif
-+}
-+
-+static inline void dx_unlock_bh(struct buffer_head *bh)
-+{
-+#ifdef CONFIG_SMP
-+ smp_mb__before_clear_bit();
-+ clear_bit(BH_DXLock, &bh->b_state);
-+#endif
-+}
-+
-+
- #ifdef CONFIG_EXT3_INDEX
- static inline unsigned dx_get_block (struct dx_entry *entry);
- static void dx_set_block (struct dx_entry *entry, unsigned value);
-@@ -153,7 +184,7 @@
- static void dx_set_limit (struct dx_entry *entries, unsigned value);
- static unsigned dx_root_limit (struct inode *dir, unsigned infosize);
- static unsigned dx_node_limit (struct inode *dir);
--static struct dx_frame *dx_probe(struct dentry *dentry,
-+static struct dx_frame *dx_probe(struct qstr *name,
- struct inode *dir,
- struct dx_hash_info *hinfo,
- struct dx_frame *frame,
-@@ -165,15 +196,18 @@
- static struct ext3_dir_entry_2 *dx_move_dirents (char *from, char *to,
- struct dx_map_entry *offsets, int count);
- static struct ext3_dir_entry_2* dx_pack_dirents (char *base, int size);
--static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block);
-+static void dx_insert_block (struct inode *, struct dx_frame *, u32, u32, u32);
- static int ext3_htree_next_block(struct inode *dir, __u32 hash,
- struct dx_frame *frame,
- struct dx_frame *frames, int *err,
- __u32 *start_hash);
- static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
-- struct ext3_dir_entry_2 **res_dir, int *err);
-+ struct ext3_dir_entry_2 **res_dir, int *err,
-+ int rwlock, void **lock);
- static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
- struct inode *inode);
-+static inline void *ext3_lock_htree(struct inode *, unsigned long, int);
-+static inline void ext3_unlock_htree(struct inode *, void *);
-
- /*
- * Future: use high four bits of block for coalesce-on-delete flags
-@@ -306,6 +340,94 @@
- #endif /* DX_DEBUG */
-
- /*
-+ * dx_find_position
-+ *
-+ * search position of specified hash in index
-+ *
-+ */
-+
-+struct dx_entry * dx_find_position(struct dx_entry * entries, u32 hash)
-+{
-+ struct dx_entry *p, *q, *m;
-+ int count;
-+
-+ count = dx_get_count(entries);
-+ p = entries + 1;
-+ q = entries + count - 1;
-+ while (p <= q)
-+ {
-+ m = p + (q - p)/2;
-+ if (dx_get_hash(m) > hash)
-+ q = m - 1;
-+ else
-+ p = m + 1;
-+ }
-+ return p - 1;
-+}
-+
-+/*
-+ * returns 1 if path is unchanged
-+ */
-+int dx_check_path(struct dx_frame *frame, u32 hash)
-+{
-+ struct dx_entry *p;
-+ int ret = 1;
-+
-+ dx_lock_bh(frame->bh);
-+ p = dx_find_position(frame->entries, hash);
-+ if (frame->leaf != dx_get_block(p))
-+ ret = 0;
-+ dx_unlock_bh(frame->bh);
-+
-+ return ret;
-+}
-+
-+/*
-+ * 0 - changed
-+ * 1 - hasn't changed
-+ */
-+static int
-+dx_check_full_path(struct dx_frame *frames, struct dx_hash_info *hinfo)
-+{
-+ struct dx_entry *p;
-+ struct dx_frame *frame = frames;
-+ u32 leaf;
-+
-+ /* check first level */
-+ dx_lock_bh(frame->bh);
-+ p = dx_find_position(frame->entries, hinfo->hash);
-+ leaf = dx_get_block(p);
-+ dx_unlock_bh(frame->bh);
-+
-+ if (leaf != frame->leaf)
-+ return 0;
-+
-+ /* is there 2nd level? */
-+ frame++;
-+ if (frame->bh == NULL)
-+ return 1;
-+
-+ /* check second level */
-+ dx_lock_bh(frame->bh);
-+
-+ /* probably 1st level got changed, check it */
-+ if (!dx_check_path(frames, hinfo->hash)) {
-+ /* path changed */
-+ dx_unlock_bh(frame->bh);
-+ return 0;
-+ }
-+
-+ p = dx_find_position(frame->entries, hinfo->hash);
-+ leaf = dx_get_block(p);
-+ dx_unlock_bh(frame->bh);
-+
-+ if (leaf != frame->leaf)
-+ return 0;
-+
-+ return 1;
-+}
-+
-+/*
- * Probe for a directory leaf block to search.
- *
- * dx_probe can return ERR_BAD_DX_DIR, which means there was a format
-@@ -315,19 +437,20 @@
- * back to userspace.
- */
- static struct dx_frame *
--dx_probe(struct dentry *dentry, struct inode *dir,
-+dx_probe(struct qstr *name, struct inode *dir,
- struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err)
- {
-- unsigned count, indirect;
-- struct dx_entry *at, *entries, *p, *q, *m;
-+ unsigned indirect;
-+ struct dx_entry *at, *entries;
- struct dx_root *root;
- struct buffer_head *bh;
- struct dx_frame *frame = frame_in;
- u32 hash;
-+ unsigned int curidx;
-
- frame->bh = NULL;
-- if (dentry)
-- dir = dentry->d_parent->d_inode;
-+ frame[1].bh = NULL;
-+
- if (!(bh = ext3_bread (NULL,dir, 0, 0, err)))
- goto fail;
- root = (struct dx_root *) bh->b_data;
-@@ -343,8 +466,8 @@
- }
- hinfo->hash_version = root->info.hash_version;
- hinfo->seed = dir->i_sb->u.ext3_sb.s_hash_seed;
-- if (dentry)
-- ext3fs_dirhash(dentry->d_name.name, dentry->d_name.len, hinfo);
-+ if (name)
-+ ext3fs_dirhash(name->name, name->len, hinfo);
- hash = hinfo->hash;
-
- if (root->info.unused_flags & 1) {
-@@ -356,7 +479,19 @@
- goto fail;
- }
-
-+repeat:
-+ curidx = 0;
-+ entries = (struct dx_entry *) (((char *)&root->info) +
-+ root->info.info_length);
-+ assert(dx_get_limit(entries) == dx_root_limit(dir,
-+ root->info.info_length));
-+ dxtrace (printk("Look up %x", hash));
-+ dx_lock_bh(bh);
-+ /* indirect must be initialized under bh lock because
-+ * 2nd level creation procedure may change it and dx_probe()
-+ * will suggest htree is still single-level -bzzz */
- if ((indirect = root->info.indirect_levels) > 1) {
-+ dx_unlock_bh(bh);
- ext3_warning(dir->i_sb, __FUNCTION__,
- "Unimplemented inode hash depth: %#06x",
- root->info.indirect_levels);
-@@ -364,56 +499,46 @@
- *err = ERR_BAD_DX_DIR;
- goto fail;
- }
--
-- entries = (struct dx_entry *) (((char *)&root->info) +
-- root->info.info_length);
-- assert(dx_get_limit(entries) == dx_root_limit(dir,
-- root->info.info_length));
-- dxtrace (printk("Look up %x", hash));
-+
- while (1)
- {
-- count = dx_get_count(entries);
-- assert (count && count <= dx_get_limit(entries));
-- p = entries + 1;
-- q = entries + count - 1;
-- while (p <= q)
-- {
-- m = p + (q - p)/2;
-- dxtrace(printk("."));
-- if (dx_get_hash(m) > hash)
-- q = m - 1;
-- else
-- p = m + 1;
-- }
--
-- if (0) // linear search cross check
-- {
-- unsigned n = count - 1;
-- at = entries;
-- while (n--)
-- {
-- dxtrace(printk(","));
-- if (dx_get_hash(++at) > hash)
-- {
-- at--;
-- break;
-- }
-- }
-- assert (at == p - 1);
-- }
--
-- at = p - 1;
-- dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at)));
-+ at = dx_find_position(entries, hinfo->hash);
-+ dxtrace(printk(" %x->%u\n",
-+ at == entries? 0: dx_get_hash(at),
-+ dx_get_block(at)));
- frame->bh = bh;
- frame->entries = entries;
- frame->at = at;
-- if (!indirect--) return frame;
-- if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err)))
-+ frame->curidx = curidx;
-+ frame->leaf = dx_get_block(at);
-+ if (!indirect--) {
-+ dx_unlock_bh(bh);
-+ return frame;
-+ }
-+
-+ /* step into next htree level */
-+ curidx = dx_get_block(at);
-+ dx_unlock_bh(bh);
-+ if (!(bh = ext3_bread (NULL,dir, frame->leaf, 0, err)))
- goto fail2;
-+
-+ dx_lock_bh(bh);
-+ /* splitting may change root index block and move
-+ * hash we're looking for into another index block
-+ * so, we have to check this situation and repeat
-+ * from begining if path got changed -bzzz */
-+ if (!dx_check_path(frame, hash)) {
-+ dx_unlock_bh(bh);
-+ bh = frame->bh;
-+ indirect++;
-+ goto repeat;
-+ }
-+
- at = entries = ((struct dx_node *) bh->b_data)->entries;
- assert (dx_get_limit(entries) == dx_node_limit (dir));
- frame++;
- }
-+ dx_unlock_bh(bh);
- fail2:
- while (frame >= frame_in) {
- brelse(frame->bh);
-@@ -427,8 +552,7 @@
- {
- if (frames[0].bh == NULL)
- return;
--
-- if (((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels)
-+ if (frames[1].bh != NULL)
- brelse(frames[1].bh);
- brelse(frames[0].bh);
- }
-@@ -470,8 +594,10 @@
- * nodes need to be read.
- */
- while (1) {
-- if (++(p->at) < p->entries + dx_get_count(p->entries))
-+ if (++(p->at) < p->entries + dx_get_count(p->entries)) {
-+ p->leaf = dx_get_block(p->at);
- break;
-+ }
- if (p == frames)
- return 0;
- num_frames++;
-@@ -497,13 +623,17 @@
- * block so no check is necessary
- */
- while (num_frames--) {
-- if (!(bh = ext3_bread(NULL, dir, dx_get_block(p->at),
-- 0, err)))
-+ u32 idx;
-+
-+ idx = p->leaf = dx_get_block(p->at);
-+ if (!(bh = ext3_bread(NULL, dir, idx, 0, err)))
- return -1; /* Failure */
- p++;
- brelse (p->bh);
- p->bh = bh;
- p->at = p->entries = ((struct dx_node *) bh->b_data)->entries;
-+ p->curidx = idx;
-+ p->leaf = dx_get_block(p->at);
- }
- return 1;
- }
-@@ -543,7 +673,7 @@
- dir = dir_file->f_dentry->d_inode;
- hinfo.hash = start_hash;
- hinfo.minor_hash = 0;
-- frame = dx_probe(0, dir_file->f_dentry->d_inode, &hinfo, frames, &err);
-+ frame = dx_probe(NULL, dir_file->f_dentry->d_inode, &hinfo, frames, &err);
- if (!frame)
- return err;
-
-@@ -625,7 +755,8 @@
- count++;
- }
- /* XXX: do we need to check rec_len == 0 case? -Chris */
-- de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
-+ de = (struct ext3_dir_entry_2 *)((char*)de +
-+ le16_to_cpu(de->rec_len));
- }
- return count;
- }
-@@ -658,7 +789,8 @@
- } while(more);
- }
-
--static void dx_insert_block(struct dx_frame *frame, u32 hash, u32 block)
-+static void dx_insert_block(struct inode *dir, struct dx_frame *frame,
-+ u32 hash, u32 block, u32 idx)
- {
- struct dx_entry *entries = frame->entries;
- struct dx_entry *old = frame->at, *new = old + 1;
-@@ -670,6 +802,7 @@
- dx_set_hash(new, hash);
- dx_set_block(new, block);
- dx_set_count(entries, count + 1);
-+
- }
- #endif
-
-@@ -752,7 +885,8 @@
-
-
- static struct buffer_head * ext3_find_entry (struct dentry *dentry,
-- struct ext3_dir_entry_2 ** res_dir)
-+ struct ext3_dir_entry_2 ** res_dir,
-+ int rwlock, void **lock)
- {
- struct super_block * sb;
- struct buffer_head * bh_use[NAMEI_RA_SIZE];
-@@ -768,6 +902,7 @@
- int namelen;
- const u8 *name;
- unsigned blocksize;
-+ int do_not_use_dx = 0;
-
- *res_dir = NULL;
- sb = dir->i_sb;
-@@ -776,9 +911,10 @@
- name = dentry->d_name.name;
- if (namelen > EXT3_NAME_LEN)
- return NULL;
-+repeat:
- #ifdef CONFIG_EXT3_INDEX
- if (is_dx(dir)) {
-- bh = ext3_dx_find_entry(dentry, res_dir, &err);
-+ bh = ext3_dx_find_entry(dentry, res_dir, &err, rwlock, lock);
- /*
- * On success, or if the error was file not found,
- * return. Otherwise, fall back to doing a search the
-@@ -787,8 +923,14 @@
- if (bh || (err != ERR_BAD_DX_DIR))
- return bh;
- dxtrace(printk("ext3_find_entry: dx failed, falling back\n"));
-+ do_not_use_dx = 1;
- }
- #endif
-+ *lock = ext3_lock_htree(dir, 0, rwlock);
-+ if (is_dx(dir) && !do_not_use_dx) {
-+ ext3_unlock_htree(dir, *lock);
-+ goto repeat;
-+ }
- nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb);
- start = EXT3_I(dir)->i_dir_start_lookup;
- if (start >= nblocks)
-@@ -859,12 +1001,17 @@
- /* Clean up the read-ahead blocks */
- for (; ra_ptr < ra_max; ra_ptr++)
- brelse (bh_use[ra_ptr]);
-+ if (!ret) {
-+ ext3_unlock_htree(dir, *lock);
-+ *lock = NULL;
-+ }
- return ret;
- }
-
- #ifdef CONFIG_EXT3_INDEX
- static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
-- struct ext3_dir_entry_2 **res_dir, int *err)
-+ struct ext3_dir_entry_2 **res_dir, int *err,
-+ int rwlock, void **lock)
- {
- struct super_block * sb;
- struct dx_hash_info hinfo;
-@@ -879,11 +1026,22 @@
- struct inode *dir = dentry->d_parent->d_inode;
-
- sb = dir->i_sb;
-- if (!(frame = dx_probe (dentry, 0, &hinfo, frames, err)))
-+repeat:
-+ if (!(frame = dx_probe (&dentry->d_name, dir, &hinfo, frames, err)))
- return NULL;
-+
-+ *lock = ext3_lock_htree(dir, frame->leaf, rwlock);
-+ /* while locking leaf we just found may get splitted
-+ * so, we need another leaf. check this */
-+ if (!dx_check_full_path(frames, &hinfo)) {
-+ ext3_unlock_htree(dir, *lock);
-+ dx_release(frames);
-+ goto repeat;
-+ }
-+
- hash = hinfo.hash;
- do {
-- block = dx_get_block(frame->at);
-+ block = frame->leaf;
- if (!(bh = ext3_bread (NULL,dir, block, 0, err)))
- goto errout;
- de = (struct ext3_dir_entry_2 *) bh->b_data;
-@@ -917,6 +1075,8 @@
- *err = -ENOENT;
- errout:
- dxtrace(printk("%s not found\n", name));
-+ ext3_unlock_htree(dir, *lock);
-+ *lock = NULL;
- dx_release (frames);
- return NULL;
- }
-@@ -927,6 +1087,7 @@
- struct inode * inode;
- struct ext3_dir_entry_2 * de;
- struct buffer_head * bh;
-+ void *lock = NULL;
-
- if (dentry->d_name.len > EXT3_NAME_LEN)
- return ERR_PTR(-ENAMETOOLONG);
-@@ -934,10 +1095,11 @@
- if (ext3_check_for_iopen(dir, dentry))
- return NULL;
-
-- bh = ext3_find_entry(dentry, &de);
-+ bh = ext3_find_entry(dentry, &de, 0, &lock);
- inode = NULL;
- if (bh) {
- unsigned long ino = le32_to_cpu(de->inode);
-+ ext3_unlock_htree(dir, lock);
- brelse (bh);
- inode = iget(dir->i_sb, ino);
-
-@@ -974,7 +1136,8 @@
- unsigned rec_len = 0;
-
- while (count--) {
-- struct ext3_dir_entry_2 *de = (struct ext3_dir_entry_2 *) (from + map->offs);
-+ struct ext3_dir_entry_2 *de =
-+ (struct ext3_dir_entry_2 *) (from + map->offs);
- rec_len = EXT3_DIR_REC_LEN(de->name_len);
- memcpy (to, de, rec_len);
- ((struct ext3_dir_entry_2 *)to)->rec_len = cpu_to_le16(rec_len);
-@@ -987,7 +1150,8 @@
-
- static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size)
- {
-- struct ext3_dir_entry_2 *next, *to, *prev, *de = (struct ext3_dir_entry_2 *) base;
-+ struct ext3_dir_entry_2 *next, *to, *prev;
-+ struct ext3_dir_entry_2 *de = (struct ext3_dir_entry_2 *) base;
- unsigned rec_len = 0;
-
- prev = to = de;
-@@ -1009,7 +1173,8 @@
-
- static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
- struct buffer_head **bh,struct dx_frame *frame,
-- struct dx_hash_info *hinfo, int *error)
-+ struct dx_hash_info *hinfo, void **target,
-+ int *error)
- {
- unsigned blocksize = dir->i_sb->s_blocksize;
- unsigned count, continued;
-@@ -1056,23 +1221,30 @@
- hash2 = map[split].hash;
- continued = hash2 == map[split - 1].hash;
- dxtrace(printk("Split block %i at %x, %i/%i\n",
-- dx_get_block(frame->at), hash2, split, count-split));
--
-+ frame->leaf, hash2, split, count-split));
-+
- /* Fancy dance to stay within two buffers */
- de2 = dx_move_dirents(data1, data2, map + split, count - split);
- de = dx_pack_dirents(data1,blocksize);
- de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
- de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2);
-- dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data1, blocksize, 1));
-- dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data2, blocksize, 1));
-+ dxtrace(dx_show_leaf(hinfo,(struct ext3_dir_entry_2*) data1, blocksize, 1));
-+ dxtrace(dx_show_leaf(hinfo,(struct ext3_dir_entry_2*) data2, blocksize, 1));
-
- /* Which block gets the new entry? */
-+ *target = NULL;
- if (hinfo->hash >= hash2)
- {
- swap(*bh, bh2);
- de = de2;
-- }
-- dx_insert_block (frame, hash2 + continued, newblock);
-+
-+ /* entry will be stored into new block
-+ * we have to lock it before add_dirent_to_buf */
-+ *target = ext3_lock_htree(dir, newblock, 1);
-+ }
-+ dx_lock_bh(frame->bh);
-+ dx_insert_block (dir, frame, hash2 + continued, newblock, frame->curidx);
-+ dx_unlock_bh(frame->bh);
- err = ext3_journal_dirty_metadata (handle, bh2);
- if (err)
- goto journal_error;
-@@ -1146,7 +1318,8 @@
- nlen = EXT3_DIR_REC_LEN(de->name_len);
- rlen = le16_to_cpu(de->rec_len);
- if (de->inode) {
-- struct ext3_dir_entry_2 *de1 = (struct ext3_dir_entry_2 *)((char *)de + nlen);
-+ struct ext3_dir_entry_2 *de1 =
-+ (struct ext3_dir_entry_2 *)((char *)de + nlen);
- de1->rec_len = cpu_to_le16(rlen - nlen);
- de->rec_len = cpu_to_le16(nlen);
- de = de1;
-@@ -1204,7 +1377,8 @@
- unsigned blocksize;
- struct dx_hash_info hinfo;
- u32 block;
--
-+ void *lock, *new_lock;
-+
- blocksize = dir->i_sb->s_blocksize;
- dxtrace(printk("Creating index\n"));
- retval = ext3_journal_get_write_access(handle, bh);
-@@ -1215,7 +1389,6 @@
- }
- root = (struct dx_root *) bh->b_data;
-
-- EXT3_I(dir)->i_flags |= EXT3_INDEX_FL;
- bh2 = ext3_append (handle, dir, &block, &retval);
- if (!(bh2)) {
- brelse(bh);
-@@ -1223,6 +1396,8 @@
- }
- data1 = bh2->b_data;
-
-+ lock = ext3_lock_htree(dir, block, 1);
-+
- /* The 0th block becomes the root, move the dirents out */
- de = (struct ext3_dir_entry_2 *)&root->dotdot;
- de = (struct ext3_dir_entry_2 *)((char *)de + le16_to_cpu(de->rec_len));
-@@ -1252,13 +1427,25 @@
- frame->entries = entries;
- frame->at = entries;
- frame->bh = bh;
-+ frame->curidx = 0;
-+ frame->leaf = 0;
-+ frame[1].bh = NULL;
- bh = bh2;
-- de = do_split(handle,dir, &bh, frame, &hinfo, &retval);
-+ de = do_split(handle,dir, &bh, frame, &hinfo, &new_lock, &retval);
- dx_release (frames);
- if (!(de))
-- return retval;
-+ goto cleanup;
-+
-+ retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
-+cleanup:
-+ if (new_lock)
-+ ext3_unlock_htree(dir, new_lock);
-+ /* we mark directory indexed in order to
-+ * avoid races while htree being created -bzzz */
-+ EXT3_I(dir)->i_flags |= EXT3_INDEX_FL;
-+ ext3_unlock_htree(dir, lock);
-
-- return add_dirent_to_buf(handle, dentry, inode, de, bh);
-+ return retval;
- }
- #endif
-
-@@ -1287,11 +1474,13 @@
- unsigned blocksize;
- unsigned nlen, rlen;
- u32 block, blocks;
-+ void *lock;
-
- sb = dir->i_sb;
- blocksize = sb->s_blocksize;
- if (!dentry->d_name.len)
- return -EINVAL;
-+repeat:
- #ifdef CONFIG_EXT3_INDEX
- if (is_dx(dir)) {
- retval = ext3_dx_add_entry(handle, dentry, inode);
-@@ -1302,36 +1491,53 @@
- ext3_mark_inode_dirty(handle, dir);
- }
- #endif
-+ lock = ext3_lock_htree(dir, 0, 1);
-+ if (is_dx(dir)) {
-+ /* we got lock for block 0
-+ * probably previous holder of the lock
-+ * created htree -bzzz */
-+ ext3_unlock_htree(dir, lock);
-+ goto repeat;
-+ }
-+
- blocks = dir->i_size >> sb->s_blocksize_bits;
- for (block = 0, offset = 0; block < blocks; block++) {
- bh = ext3_bread(handle, dir, block, 0, &retval);
-- if(!bh)
-+ if(!bh) {
-+ ext3_unlock_htree(dir, lock);
- return retval;
-+ }
- retval = add_dirent_to_buf(handle, dentry, inode, 0, bh);
-- if (retval != -ENOSPC)
-+ if (retval != -ENOSPC) {
-+ ext3_unlock_htree(dir, lock);
- return retval;
-+ }
-
- #ifdef CONFIG_EXT3_INDEX
- if (blocks == 1 && !dx_fallback &&
-- EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX))
-- return make_indexed_dir(handle, dentry, inode, bh);
-+ EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX)) {
-+ retval = make_indexed_dir(handle, dentry, inode, bh);
-+ ext3_unlock_htree(dir, lock);
-+ return retval;
-+ }
- #endif
- brelse(bh);
- }
- bh = ext3_append(handle, dir, &block, &retval);
-- if (!bh)
-+ if (!bh) {
-+ ext3_unlock_htree(dir, lock);
- return retval;
-+ }
- de = (struct ext3_dir_entry_2 *) bh->b_data;
- de->inode = 0;
- de->rec_len = cpu_to_le16(rlen = blocksize);
- nlen = 0;
-- return add_dirent_to_buf(handle, dentry, inode, de, bh);
-+ retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
-+ ext3_unlock_htree(dir, lock);
-+ return retval;
- }
-
- #ifdef CONFIG_EXT3_INDEX
--/*
-- * Returns 0 for success, or a negative error value
-- */
- static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
- struct inode *inode)
- {
-@@ -1343,15 +1549,28 @@
- struct super_block * sb = dir->i_sb;
- struct ext3_dir_entry_2 *de;
- int err;
--
-- frame = dx_probe(dentry, 0, &hinfo, frames, &err);
-+ int curidx;
-+ void *idx_lock, *leaf_lock, *newleaf_lock;
-+
-+repeat:
-+ frame = dx_probe(&dentry->d_name, dir, &hinfo, frames, &err);
- if (!frame)
- return err;
-- entries = frame->entries;
-- at = frame->at;
-
-- if (!(bh = ext3_bread(handle,dir, dx_get_block(frame->at), 0, &err)))
-+ /* we're going to chage leaf, so lock it first */
-+ leaf_lock = ext3_lock_htree(dir, frame->leaf, 1);
-+
-+ /* while locking leaf we just found may get splitted
-+ * so we need to check this */
-+ if (!dx_check_full_path(frames, &hinfo)) {
-+ ext3_unlock_htree(dir, leaf_lock);
-+ dx_release(frames);
-+ goto repeat;
-+ }
-+ if (!(bh = ext3_bread(handle,dir, frame->leaf, 0, &err))) {
-+ printk("can't ext3_bread(%d) = %d\n", (int) frame->leaf, err);
- goto cleanup;
-+ }
-
- BUFFER_TRACE(bh, "get_write_access");
- err = ext3_journal_get_write_access(handle, bh);
-@@ -1364,6 +1583,35 @@
- goto cleanup;
- }
-
-+ /* our leaf has no enough space. hence, we have to
-+ * split it. so lock index for this leaf first */
-+ curidx = frame->curidx;
-+ idx_lock = ext3_lock_htree(dir, curidx, 1);
-+
-+ /* now check did path get changed? */
-+ dx_release(frames);
-+
-+ frame = dx_probe(&dentry->d_name, dentry->d_parent->d_inode,
-+ &hinfo, frames, &err);
-+ if (!frame) {
-+ /* FIXME: error handling here */
-+ brelse(bh);
-+ ext3_unlock_htree(dir, idx_lock);
-+ return err;
-+ }
-+
-+ if (frame->curidx != curidx) {
-+ /* path has been changed. we have to drop old lock
-+ * and repeat */
-+ brelse(bh);
-+ ext3_unlock_htree(dir, idx_lock);
-+ ext3_unlock_htree(dir, leaf_lock);
-+ dx_release(frames);
-+ goto repeat;
-+ }
-+ entries = frame->entries;
-+ at = frame->at;
-+
- /* Block full, should compress but for now just split */
- dxtrace(printk("using %u of %u node entries\n",
- dx_get_count(entries), dx_get_limit(entries)));
-@@ -1375,7 +1623,8 @@
- struct dx_entry *entries2;
- struct dx_node *node2;
- struct buffer_head *bh2;
--
-+ void *nb_lock;
-+
- if (levels && (dx_get_count(frames->entries) ==
- dx_get_limit(frames->entries))) {
- ext3_warning(sb, __FUNCTION__,
-@@ -1386,6 +1635,7 @@
- bh2 = ext3_append (handle, dir, &newblock, &err);
- if (!(bh2))
- goto cleanup;
-+ nb_lock = ext3_lock_htree(dir, newblock, 1);
- node2 = (struct dx_node *)(bh2->b_data);
- entries2 = node2->entries;
- node2->fake.rec_len = cpu_to_le16(sb->s_blocksize);
-@@ -1397,27 +1647,73 @@
- if (levels) {
- unsigned icount1 = icount/2, icount2 = icount - icount1;
- unsigned hash2 = dx_get_hash(entries + icount1);
-+ void *ri_lock;
-+
-+ /* we have to protect root htree index against
-+ * another dx_add_entry() which would want to
-+ * split it too -bzzz */
-+ ri_lock = ext3_lock_htree(dir, 0, 1);
-+
-+ /* as root index block blocked we must repeat
-+ * searching for current position of our 2nd index -bzzz */
-+ dx_lock_bh(frame->bh);
-+ frames->at = dx_find_position(frames->entries, hinfo.hash);
-+ dx_unlock_bh(frame->bh);
-+
- dxtrace(printk("Split index %i/%i\n", icount1, icount2));
--
-- BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */
-+
-+ BUFFER_TRACE(frame->bh, "get_write_access");
- err = ext3_journal_get_write_access(handle,
- frames[0].bh);
- if (err)
- goto journal_error;
--
-+
-+ /* copy index into new one */
- memcpy ((char *) entries2, (char *) (entries + icount1),
- icount2 * sizeof(struct dx_entry));
-- dx_set_count (entries, icount1);
- dx_set_count (entries2, icount2);
- dx_set_limit (entries2, dx_node_limit(dir));
-
- /* Which index block gets the new entry? */
- if (at - entries >= icount1) {
-+ /* unlock index we won't use */
-+ ext3_unlock_htree(dir, idx_lock);
-+ idx_lock = nb_lock;
- frame->at = at = at - entries - icount1 + entries2;
-- frame->entries = entries = entries2;
-+ frame->entries = entries2;
-+ frame->curidx = curidx = newblock;
- swap(frame->bh, bh2);
-+ } else {
-+ /* we'll use old index,so new one may be freed */
-+ ext3_unlock_htree(dir, nb_lock);
- }
-- dx_insert_block (frames + 0, hash2, newblock);
-+
-+ /* NOTE: very subtle piece of code
-+ * competing dx_probe() may find 2nd level index in root
-+ * index, then we insert new index here and set new count
-+ * in that 2nd level index. so, dx_probe() may see 2nd
-+ * level index w/o hash it looks for. the solution is
-+ * to check root index after we locked just founded 2nd
-+ * level index -bzzz */
-+ dx_lock_bh(frames[0].bh);
-+ dx_insert_block (dir, frames + 0, hash2, newblock, 0);
-+ dx_unlock_bh(frames[0].bh);
-+
-+ /* now old and new 2nd level index blocks contain
-+ * all pointers, so dx_probe() may find it in the both.
-+ * it's OK -bzzz */
-+
-+ dx_lock_bh(frame->bh);
-+ dx_set_count(entries, icount1);
-+ dx_unlock_bh(frame->bh);
-+
-+ /* now old 2nd level index block points to first half
-+ * of leafs. it's importand that dx_probe() must
-+ * check root index block for changes under
-+ * dx_lock_bh(frame->bh) -bzzz */
-+
-+ ext3_unlock_htree(dir, ri_lock);
-+
- dxtrace(dx_show_index ("node", frames[1].entries));
- dxtrace(dx_show_index ("node",
- ((struct dx_node *) bh2->b_data)->entries));
-@@ -1426,38 +1722,61 @@
- goto journal_error;
- brelse (bh2);
- } else {
-+ unsigned long leaf = frame->leaf;
-+
- dxtrace(printk("Creating second level index...\n"));
- memcpy((char *) entries2, (char *) entries,
- icount * sizeof(struct dx_entry));
- dx_set_limit(entries2, dx_node_limit(dir));
-
- /* Set up root */
-+ dx_lock_bh(frames[0].bh);
- dx_set_count(entries, 1);
- dx_set_block(entries + 0, newblock);
- ((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels = 1;
-+ dx_unlock_bh(frames[0].bh);
-
- /* Add new access path frame */
- frame = frames + 1;
- frame->at = at = at - entries + entries2;
- frame->entries = entries = entries2;
- frame->bh = bh2;
-+ frame->curidx = newblock;
-+ frame->leaf = leaf;
- err = ext3_journal_get_write_access(handle,
- frame->bh);
- if (err)
- goto journal_error;
-+
-+ /* first level index was root. it's already initialized */
-+ /* we my unlock it now */
-+ ext3_unlock_htree(dir, idx_lock);
-+
-+ /* current index is just created 2nd level index */
-+ curidx = newblock;
-+ idx_lock = nb_lock;
- }
- ext3_journal_dirty_metadata(handle, frames[0].bh);
- }
-- de = do_split(handle, dir, &bh, frame, &hinfo, &err);
-+ de = do_split(handle, dir, &bh, frame, &hinfo, &newleaf_lock, &err);
- if (!de)
- goto cleanup;
-+
-+ /* index splitted */
-+ ext3_unlock_htree(dir, idx_lock);
-+
- err = add_dirent_to_buf(handle, dentry, inode, de, bh);
-+
-+ if (newleaf_lock)
-+ ext3_unlock_htree(dir, newleaf_lock);
-+
- bh = 0;
- goto cleanup;
-
- journal_error:
- ext3_std_error(dir->i_sb, err);
- cleanup:
-+ ext3_unlock_htree(dir, leaf_lock);
- if (bh)
- brelse(bh);
- dx_release(frames);
-@@ -1905,6 +2224,7 @@
- struct buffer_head * bh;
- struct ext3_dir_entry_2 * de;
- handle_t *handle;
-+ void *lock;
-
- handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
- if (IS_ERR(handle)) {
-@@ -1912,7 +2232,7 @@
- }
-
- retval = -ENOENT;
-- bh = ext3_find_entry (dentry, &de);
-+ bh = ext3_find_entry (dentry, &de, 1, &lock);
- if (!bh)
- goto end_rmdir;
-
-@@ -1923,14 +2243,19 @@
- DQUOT_INIT(inode);
-
- retval = -EIO;
-- if (le32_to_cpu(de->inode) != inode->i_ino)
-+ if (le32_to_cpu(de->inode) != inode->i_ino) {
-+ ext3_unlock_htree(dir, lock);
- goto end_rmdir;
-+ }
-
- retval = -ENOTEMPTY;
-- if (!empty_dir (inode))
-+ if (!empty_dir (inode)) {
-+ ext3_unlock_htree(dir, lock);
- goto end_rmdir;
-+ }
-
- retval = ext3_delete_entry(handle, dir, de, bh);
-+ ext3_unlock_htree(dir, lock);
- if (retval)
- goto end_rmdir;
- if (inode->i_nlink != 2)
-@@ -1989,6 +2314,7 @@
- struct buffer_head * bh;
- struct ext3_dir_entry_2 * de;
- handle_t *handle;
-+ void *lock;
-
- handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
- if (IS_ERR(handle)) {
-@@ -1999,7 +2325,7 @@
- handle->h_sync = 1;
-
- retval = -ENOENT;
-- bh = ext3_find_entry (dentry, &de);
-+ bh = ext3_find_entry (dentry, &de, 1, &lock);
- if (!bh)
- goto end_unlink;
-
-@@ -2007,8 +2333,10 @@
- DQUOT_INIT(inode);
-
- retval = -EIO;
-- if (le32_to_cpu(de->inode) != inode->i_ino)
-+ if (le32_to_cpu(de->inode) != inode->i_ino) {
-+ ext3_unlock_htree(dir, lock);
- goto end_unlink;
-+ }
-
- if (!inode->i_nlink) {
- ext3_warning (inode->i_sb, "ext3_unlink",
-@@ -2017,6 +2345,7 @@
- inode->i_nlink = 1;
- }
- retval = ext3_delete_entry(handle, dir, de, bh);
-+ ext3_unlock_htree(dir, lock);
- if (retval)
- goto end_unlink;
- dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-@@ -2155,6 +2484,7 @@
- struct buffer_head * old_bh, * new_bh, * dir_bh;
- struct ext3_dir_entry_2 * old_de, * new_de;
- int retval;
-+ void *lock1 = NULL, *lock2 = NULL, *lock3 = NULL;
-
- old_bh = new_bh = dir_bh = NULL;
-
-@@ -2167,7 +2497,10 @@
- if (IS_SYNC(old_dir) || IS_SYNC(new_dir))
- handle->h_sync = 1;
-
-- old_bh = ext3_find_entry (old_dentry, &old_de);
-+ if (old_dentry->d_parent == new_dentry->d_parent)
-+ down(&EXT3_I(old_dentry->d_parent->d_inode)->i_rename_sem);
-+
-+ old_bh = ext3_find_entry (old_dentry, &old_de, 1, &lock1 /* FIXME */);
- /*
- * Check for inode number is _not_ due to possible IO errors.
- * We might rmdir the source, keep it as pwd of some process
-@@ -2180,7 +2513,7 @@
- goto end_rename;
-
- new_inode = new_dentry->d_inode;
-- new_bh = ext3_find_entry (new_dentry, &new_de);
-+ new_bh = ext3_find_entry (new_dentry, &new_de, 1, &lock2 /* FIXME */);
- if (new_bh) {
- if (!new_inode) {
- brelse (new_bh);
-@@ -2247,7 +2580,7 @@
- struct buffer_head *old_bh2;
- struct ext3_dir_entry_2 *old_de2;
-
-- old_bh2 = ext3_find_entry(old_dentry, &old_de2);
-+ old_bh2 = ext3_find_entry(old_dentry, &old_de2, 1, &lock3 /* FIXME */);
- if (old_bh2) {
- retval = ext3_delete_entry(handle, old_dir,
- old_de2, old_bh2);
-@@ -2290,6 +2623,14 @@
- retval = 0;
-
- end_rename:
-+ if (lock1)
-+ ext3_unlock_htree(old_dentry->d_parent->d_inode, lock1);
-+ if (lock2)
-+ ext3_unlock_htree(new_dentry->d_parent->d_inode, lock2);
-+ if (lock3)
-+ ext3_unlock_htree(old_dentry->d_parent->d_inode, lock3);
-+ if (old_dentry->d_parent == new_dentry->d_parent)
-+ up(&EXT3_I(old_dentry->d_parent->d_inode)->i_rename_sem);
- brelse (dir_bh);
- brelse (old_bh);
- brelse (new_bh);
-@@ -2298,6 +2639,29 @@
- }
-
- /*
-+ * this locking primitives are used to protect parts
-+ * of dir's htree. protection unit is block: leaf or index
-+ */
-+static inline void *ext3_lock_htree(struct inode *dir,
-+ unsigned long value, int rwlock)
-+{
-+ void *lock;
-+
-+ if (!test_opt(dir->i_sb, PDIROPS))
-+ return NULL;
-+ lock = dynlock_lock(&EXT3_I(dir)->i_htree_lock, value, 1, GFP_KERNEL);
-+ return lock;
-+}
-+
-+static inline void ext3_unlock_htree(struct inode *dir,
-+ void *lock)
-+{
-+ if (!test_opt(dir->i_sb, PDIROPS) || !lock)
-+ return;
-+ dynlock_unlock(&EXT3_I(dir)->i_htree_lock, lock);
-+}
-+
-+/*
- * directories can handle most operations...
- */
- struct inode_operations ext3_dir_inode_operations = {
-Index: lum/fs/ext3/super.c
-===================================================================
---- lum.orig/fs/ext3/super.c 2004-06-03 16:32:28.000000000 -0400
-+++ lum/fs/ext3/super.c 2004-06-03 16:37:15.000000000 -0400
-@@ -733,6 +733,9 @@
- if (want_numeric(value, "sb", sb_block))
- return 0;
- }
-+ else if (!strcmp (this_char, "pdirops")) {
-+ set_opt (sbi->s_mount_opt, PDIROPS);
-+ }
- #ifdef CONFIG_JBD_DEBUG
- else if (!strcmp (this_char, "ro-after")) {
- unsigned long v;
-@@ -896,6 +899,10 @@
- ext3_check_inodes_bitmap (sb);
- }
- #endif
-+#ifdef S_PDIROPS
-+ if (test_opt (sb, PDIROPS))
-+ sb->s_flags |= S_PDIROPS;
-+#endif
- setup_ro_after(sb);
- return res;
- }
-@@ -1400,6 +1407,11 @@
-
- ext3_ext_init(sb);
-
-+ if (test_opt(sb, PDIROPS)) {
-+ printk (KERN_INFO "EXT3-fs: mounted filesystem with parallel dirops\n");
-+ sb->s_flags |= S_PDIROPS;
-+ }
-+
- return sb;
-
- failed_mount3:
-Index: lum/fs/ext3/inode.c
-===================================================================
---- lum.orig/fs/ext3/inode.c 2004-06-03 16:32:29.000000000 -0400
-+++ lum/fs/ext3/inode.c 2004-06-03 16:37:15.000000000 -0400
-@@ -2251,6 +2251,9 @@
- } else if (S_ISDIR(inode->i_mode)) {
- inode->i_op = &ext3_dir_inode_operations;
- inode->i_fop = &ext3_dir_operations;
-+ dynlock_init(&EXT3_I(inode)->i_htree_lock);
-+ sema_init(&EXT3_I(inode)->i_rename_sem, 1);
-+ sema_init(&EXT3_I(inode)->i_append_sem, 1);
- } else if (S_ISLNK(inode->i_mode)) {
- if (ext3_inode_is_fast_symlink(inode))
- inode->i_op = &ext3_fast_symlink_inode_operations;
-Index: lum/fs/ext3/ialloc.c
-===================================================================
---- lum.orig/fs/ext3/ialloc.c 2004-06-03 16:32:28.000000000 -0400
-+++ lum/fs/ext3/ialloc.c 2004-06-03 16:37:15.000000000 -0400
-@@ -609,6 +609,9 @@
- return ERR_PTR(-EDQUOT);
- }
- ext3_debug ("allocating inode %lu\n", inode->i_ino);
-+ dynlock_init(&EXT3_I(inode)->i_htree_lock);
-+ sema_init(&EXT3_I(inode)->i_rename_sem, 1);
-+ sema_init(&EXT3_I(inode)->i_append_sem, 1);
- return inode;
-
- fail:
-Index: lum/include/linux/ext3_fs.h
-===================================================================
---- lum.orig/include/linux/ext3_fs.h 2004-06-03 16:32:28.000000000 -0400
-+++ lum/include/linux/ext3_fs.h 2004-06-03 16:37:15.000000000 -0400
-@@ -320,6 +320,7 @@
- /*
- * Mount flags
- */
-+#define EXT3_MOUNT_PDIROPS 0x800000/* Parallel dir operations */
- #define EXT3_MOUNT_CHECK 0x0001 /* Do mount-time checks */
- #define EXT3_MOUNT_GRPID 0x0004 /* Create files with directory's group */
- #define EXT3_MOUNT_DEBUG 0x0008 /* Some debugging messages */
-Index: lum/include/linux/ext3_fs_i.h
-===================================================================
---- lum.orig/include/linux/ext3_fs_i.h 2004-06-03 16:32:28.000000000 -0400
-+++ lum/include/linux/ext3_fs_i.h 2004-06-03 16:37:15.000000000 -0400
-@@ -17,6 +17,7 @@
- #define _LINUX_EXT3_FS_I
-
- #include <linux/rwsem.h>
-+#include <linux/dynlocks.h>
-
- /*
- * second extended file system inode data in memory
-@@ -76,6 +77,11 @@
- * by other means, so we have truncate_sem.
- */
- struct rw_semaphore truncate_sem;
-+
-+ /* following fields for parallel directory operations -bzzz */
-+ struct dynlock i_htree_lock;
-+ struct semaphore i_append_sem;
-+ struct semaphore i_rename_sem;
-
- __u32 i_cached_extent[3];
- };
+++ /dev/null
- fs/ext3/ialloc.c | 3
- fs/ext3/inode.c | 3
- fs/ext3/namei.c | 582 +++++++++++++++++++++++++++++++++++++---------
- fs/ext3/super.c | 14 +
- include/linux/ext3_fs.h | 1
- include/linux/ext3_fs_i.h | 6
- 6 files changed, 500 insertions(+), 109 deletions(-)
-
-Index: linux-2.4.24/fs/ext3/namei.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/namei.c 2004-04-01 20:22:17.000000000 +0400
-+++ linux-2.4.24/fs/ext3/namei.c 2004-04-01 20:24:48.000000000 +0400
-@@ -51,6 +51,9 @@
- {
- struct buffer_head *bh;
-
-+ /* with parallel dir operations all appends
-+ * have to be serialized -bzzz */
-+ down(&EXT3_I(inode)->i_append_sem);
- *block = inode->i_size >> inode->i_sb->s_blocksize_bits;
-
- if ((bh = ext3_bread(handle, inode, *block, 1, err))) {
-@@ -58,6 +61,8 @@
- EXT3_I(inode)->i_disksize = inode->i_size;
- ext3_journal_get_write_access(handle,bh);
- }
-+ up(&EXT3_I(inode)->i_append_sem);
-+
- return bh;
- }
-
-@@ -134,6 +139,8 @@
- struct buffer_head *bh;
- struct dx_entry *entries;
- struct dx_entry *at;
-+ unsigned long leaf;
-+ unsigned int curidx;
- };
-
- struct dx_map_entry
-@@ -142,6 +149,30 @@
- u32 offs;
- };
-
-+/* FIXME: this should be reworked using bb_spin_lock
-+ * introduced in -mm tree
-+ */
-+#define BH_DXLock 25
-+
-+static inline void dx_lock_bh(struct buffer_head volatile *bh)
-+{
-+#ifdef CONFIG_SMP
-+ while (test_and_set_bit(BH_DXLock, &bh->b_state)) {
-+ while (test_bit(BH_DXLock, &bh->b_state))
-+ cpu_relax();
-+ }
-+#endif
-+}
-+
-+static inline void dx_unlock_bh(struct buffer_head *bh)
-+{
-+#ifdef CONFIG_SMP
-+ smp_mb__before_clear_bit();
-+ clear_bit(BH_DXLock, &bh->b_state);
-+#endif
-+}
-+
-+
- #ifdef CONFIG_EXT3_INDEX
- static inline unsigned dx_get_block (struct dx_entry *entry);
- static void dx_set_block (struct dx_entry *entry, unsigned value);
-@@ -153,7 +184,7 @@
- static void dx_set_limit (struct dx_entry *entries, unsigned value);
- static unsigned dx_root_limit (struct inode *dir, unsigned infosize);
- static unsigned dx_node_limit (struct inode *dir);
--static struct dx_frame *dx_probe(struct dentry *dentry,
-+static struct dx_frame *dx_probe(struct qstr *name,
- struct inode *dir,
- struct dx_hash_info *hinfo,
- struct dx_frame *frame,
-@@ -165,15 +196,18 @@
- static struct ext3_dir_entry_2 *dx_move_dirents (char *from, char *to,
- struct dx_map_entry *offsets, int count);
- static struct ext3_dir_entry_2* dx_pack_dirents (char *base, int size);
--static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block);
-+static void dx_insert_block (struct inode *, struct dx_frame *, u32, u32, u32);
- static int ext3_htree_next_block(struct inode *dir, __u32 hash,
- struct dx_frame *frame,
- struct dx_frame *frames, int *err,
- __u32 *start_hash);
- static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
-- struct ext3_dir_entry_2 **res_dir, int *err);
-+ struct ext3_dir_entry_2 **res_dir, int *err,
-+ int rwlock, void **lock);
- static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
- struct inode *inode);
-+static inline void *ext3_lock_htree(struct inode *, unsigned long, int);
-+static inline void ext3_unlock_htree(struct inode *, void *);
-
- /*
- * Future: use high four bits of block for coalesce-on-delete flags
-@@ -306,6 +340,94 @@
- #endif /* DX_DEBUG */
-
- /*
-+ * dx_find_position
-+ *
-+ * search position of specified hash in index
-+ *
-+ */
-+
-+struct dx_entry * dx_find_position(struct dx_entry * entries, u32 hash)
-+{
-+ struct dx_entry *p, *q, *m;
-+ int count;
-+
-+ count = dx_get_count(entries);
-+ p = entries + 1;
-+ q = entries + count - 1;
-+ while (p <= q)
-+ {
-+ m = p + (q - p)/2;
-+ if (dx_get_hash(m) > hash)
-+ q = m - 1;
-+ else
-+ p = m + 1;
-+ }
-+ return p - 1;
-+}
-+
-+/*
-+ * returns 1 if path is unchanged
-+ */
-+int dx_check_path(struct dx_frame *frame, u32 hash)
-+{
-+ struct dx_entry *p;
-+ int ret = 1;
-+
-+ dx_lock_bh(frame->bh);
-+ p = dx_find_position(frame->entries, hash);
-+ if (frame->leaf != dx_get_block(p))
-+ ret = 0;
-+ dx_unlock_bh(frame->bh);
-+
-+ return ret;
-+}
-+
-+/*
-+ * 0 - changed
-+ * 1 - hasn't changed
-+ */
-+static int
-+dx_check_full_path(struct dx_frame *frames, struct dx_hash_info *hinfo)
-+{
-+ struct dx_entry *p;
-+ struct dx_frame *frame = frames;
-+ u32 leaf;
-+
-+ /* check first level */
-+ dx_lock_bh(frame->bh);
-+ p = dx_find_position(frame->entries, hinfo->hash);
-+ leaf = dx_get_block(p);
-+ dx_unlock_bh(frame->bh);
-+
-+ if (leaf != frame->leaf)
-+ return 0;
-+
-+ /* is there 2nd level? */
-+ frame++;
-+ if (frame->bh == NULL)
-+ return 1;
-+
-+ /* check second level */
-+ dx_lock_bh(frame->bh);
-+
-+ /* probably 1st level got changed, check it */
-+ if (!dx_check_path(frames, hinfo->hash)) {
-+ /* path changed */
-+ dx_unlock_bh(frame->bh);
-+ return 0;
-+ }
-+
-+ p = dx_find_position(frame->entries, hinfo->hash);
-+ leaf = dx_get_block(p);
-+ dx_unlock_bh(frame->bh);
-+
-+ if (leaf != frame->leaf)
-+ return 0;
-+
-+ return 1;
-+}
-+
-+/*
- * Probe for a directory leaf block to search.
- *
- * dx_probe can return ERR_BAD_DX_DIR, which means there was a format
-@@ -315,19 +437,20 @@
- * back to userspace.
- */
- static struct dx_frame *
--dx_probe(struct dentry *dentry, struct inode *dir,
-+dx_probe(struct qstr *name, struct inode *dir,
- struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err)
- {
-- unsigned count, indirect;
-- struct dx_entry *at, *entries, *p, *q, *m;
-+ unsigned indirect;
-+ struct dx_entry *at, *entries;
- struct dx_root *root;
- struct buffer_head *bh;
- struct dx_frame *frame = frame_in;
- u32 hash;
-+ unsigned int curidx;
-
- frame->bh = NULL;
-- if (dentry)
-- dir = dentry->d_parent->d_inode;
-+ frame[1].bh = NULL;
-+
- if (!(bh = ext3_bread (NULL,dir, 0, 0, err)))
- goto fail;
- root = (struct dx_root *) bh->b_data;
-@@ -343,8 +466,8 @@
- }
- hinfo->hash_version = root->info.hash_version;
- hinfo->seed = dir->i_sb->u.ext3_sb.s_hash_seed;
-- if (dentry)
-- ext3fs_dirhash(dentry->d_name.name, dentry->d_name.len, hinfo);
-+ if (name)
-+ ext3fs_dirhash(name->name, name->len, hinfo);
- hash = hinfo->hash;
-
- if (root->info.unused_flags & 1) {
-@@ -356,7 +479,19 @@
- goto fail;
- }
-
-+repeat:
-+ curidx = 0;
-+ entries = (struct dx_entry *) (((char *)&root->info) +
-+ root->info.info_length);
-+ assert(dx_get_limit(entries) == dx_root_limit(dir,
-+ root->info.info_length));
-+ dxtrace (printk("Look up %x", hash));
-+ dx_lock_bh(bh);
-+ /* indirect must be initialized under bh lock because
-+ * 2nd level creation procedure may change it and dx_probe()
-+ * will suggest htree is still single-level -bzzz */
- if ((indirect = root->info.indirect_levels) > 1) {
-+ dx_unlock_bh(bh);
- ext3_warning(dir->i_sb, __FUNCTION__,
- "Unimplemented inode hash depth: %#06x",
- root->info.indirect_levels);
-@@ -364,56 +499,46 @@
- *err = ERR_BAD_DX_DIR;
- goto fail;
- }
--
-- entries = (struct dx_entry *) (((char *)&root->info) +
-- root->info.info_length);
-- assert(dx_get_limit(entries) == dx_root_limit(dir,
-- root->info.info_length));
-- dxtrace (printk("Look up %x", hash));
-+
- while (1)
- {
-- count = dx_get_count(entries);
-- assert (count && count <= dx_get_limit(entries));
-- p = entries + 1;
-- q = entries + count - 1;
-- while (p <= q)
-- {
-- m = p + (q - p)/2;
-- dxtrace(printk("."));
-- if (dx_get_hash(m) > hash)
-- q = m - 1;
-- else
-- p = m + 1;
-- }
--
-- if (0) // linear search cross check
-- {
-- unsigned n = count - 1;
-- at = entries;
-- while (n--)
-- {
-- dxtrace(printk(","));
-- if (dx_get_hash(++at) > hash)
-- {
-- at--;
-- break;
-- }
-- }
-- assert (at == p - 1);
-- }
--
-- at = p - 1;
-- dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at)));
-+ at = dx_find_position(entries, hinfo->hash);
-+ dxtrace(printk(" %x->%u\n",
-+ at == entries? 0: dx_get_hash(at),
-+ dx_get_block(at)));
- frame->bh = bh;
- frame->entries = entries;
- frame->at = at;
-- if (!indirect--) return frame;
-- if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err)))
-+ frame->curidx = curidx;
-+ frame->leaf = dx_get_block(at);
-+ if (!indirect--) {
-+ dx_unlock_bh(bh);
-+ return frame;
-+ }
-+
-+ /* step into next htree level */
-+ curidx = dx_get_block(at);
-+ dx_unlock_bh(bh);
-+ if (!(bh = ext3_bread (NULL,dir, frame->leaf, 0, err)))
- goto fail2;
-+
-+ dx_lock_bh(bh);
-+ /* splitting may change root index block and move
-+ * hash we're looking for into another index block
-+ * so, we have to check this situation and repeat
-+ * from begining if path got changed -bzzz */
-+ if (!dx_check_path(frame, hash)) {
-+ dx_unlock_bh(bh);
-+ bh = frame->bh;
-+ indirect++;
-+ goto repeat;
-+ }
-+
- at = entries = ((struct dx_node *) bh->b_data)->entries;
- assert (dx_get_limit(entries) == dx_node_limit (dir));
- frame++;
- }
-+ dx_unlock_bh(bh);
- fail2:
- while (frame >= frame_in) {
- brelse(frame->bh);
-@@ -427,8 +552,7 @@
- {
- if (frames[0].bh == NULL)
- return;
--
-- if (((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels)
-+ if (frames[1].bh != NULL)
- brelse(frames[1].bh);
- brelse(frames[0].bh);
- }
-@@ -470,8 +594,10 @@
- * nodes need to be read.
- */
- while (1) {
-- if (++(p->at) < p->entries + dx_get_count(p->entries))
-+ if (++(p->at) < p->entries + dx_get_count(p->entries)) {
-+ p->leaf = dx_get_block(p->at);
- break;
-+ }
- if (p == frames)
- return 0;
- num_frames++;
-@@ -497,13 +623,17 @@
- * block so no check is necessary
- */
- while (num_frames--) {
-- if (!(bh = ext3_bread(NULL, dir, dx_get_block(p->at),
-- 0, err)))
-+ u32 idx;
-+
-+ idx = p->leaf = dx_get_block(p->at);
-+ if (!(bh = ext3_bread(NULL, dir, idx, 0, err)))
- return -1; /* Failure */
- p++;
- brelse (p->bh);
- p->bh = bh;
- p->at = p->entries = ((struct dx_node *) bh->b_data)->entries;
-+ p->curidx = idx;
-+ p->leaf = dx_get_block(p->at);
- }
- return 1;
- }
-@@ -543,7 +673,7 @@
- dir = dir_file->f_dentry->d_inode;
- hinfo.hash = start_hash;
- hinfo.minor_hash = 0;
-- frame = dx_probe(0, dir_file->f_dentry->d_inode, &hinfo, frames, &err);
-+ frame = dx_probe(NULL, dir_file->f_dentry->d_inode, &hinfo, frames, &err);
- if (!frame)
- return err;
-
-@@ -625,7 +755,8 @@
- count++;
- }
- /* XXX: do we need to check rec_len == 0 case? -Chris */
-- de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
-+ de = (struct ext3_dir_entry_2 *)((char*)de +
-+ le16_to_cpu(de->rec_len));
- }
- return count;
- }
-@@ -658,7 +789,8 @@
- } while(more);
- }
-
--static void dx_insert_block(struct dx_frame *frame, u32 hash, u32 block)
-+static void dx_insert_block(struct inode *dir, struct dx_frame *frame,
-+ u32 hash, u32 block, u32 idx)
- {
- struct dx_entry *entries = frame->entries;
- struct dx_entry *old = frame->at, *new = old + 1;
-@@ -670,6 +802,7 @@
- dx_set_hash(new, hash);
- dx_set_block(new, block);
- dx_set_count(entries, count + 1);
-+
- }
- #endif
-
-@@ -752,7 +885,8 @@
-
-
- static struct buffer_head * ext3_find_entry (struct dentry *dentry,
-- struct ext3_dir_entry_2 ** res_dir)
-+ struct ext3_dir_entry_2 ** res_dir,
-+ int rwlock, void **lock)
- {
- struct super_block * sb;
- struct buffer_head * bh_use[NAMEI_RA_SIZE];
-@@ -768,6 +902,7 @@
- int namelen;
- const u8 *name;
- unsigned blocksize;
-+ int do_not_use_dx = 0;
-
- *res_dir = NULL;
- sb = dir->i_sb;
-@@ -776,9 +911,10 @@
- name = dentry->d_name.name;
- if (namelen > EXT3_NAME_LEN)
- return NULL;
-+repeat:
- #ifdef CONFIG_EXT3_INDEX
- if (is_dx(dir)) {
-- bh = ext3_dx_find_entry(dentry, res_dir, &err);
-+ bh = ext3_dx_find_entry(dentry, res_dir, &err, rwlock, lock);
- /*
- * On success, or if the error was file not found,
- * return. Otherwise, fall back to doing a search the
-@@ -787,8 +923,14 @@
- if (bh || (err != ERR_BAD_DX_DIR))
- return bh;
- dxtrace(printk("ext3_find_entry: dx failed, falling back\n"));
-+ do_not_use_dx = 1;
- }
- #endif
-+ *lock = ext3_lock_htree(dir, 0, rwlock);
-+ if (is_dx(dir) && !do_not_use_dx) {
-+ ext3_unlock_htree(dir, *lock);
-+ goto repeat;
-+ }
- nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb);
- start = EXT3_I(dir)->i_dir_start_lookup;
- if (start >= nblocks)
-@@ -859,12 +1001,17 @@
- /* Clean up the read-ahead blocks */
- for (; ra_ptr < ra_max; ra_ptr++)
- brelse (bh_use[ra_ptr]);
-+ if (!ret) {
-+ ext3_unlock_htree(dir, *lock);
-+ *lock = NULL;
-+ }
- return ret;
- }
-
- #ifdef CONFIG_EXT3_INDEX
- static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
-- struct ext3_dir_entry_2 **res_dir, int *err)
-+ struct ext3_dir_entry_2 **res_dir, int *err,
-+ int rwlock, void **lock)
- {
- struct super_block * sb;
- struct dx_hash_info hinfo;
-@@ -879,11 +1026,22 @@
- struct inode *dir = dentry->d_parent->d_inode;
-
- sb = dir->i_sb;
-- if (!(frame = dx_probe (dentry, 0, &hinfo, frames, err)))
-+repeat:
-+ if (!(frame = dx_probe (&dentry->d_name, dir, &hinfo, frames, err)))
- return NULL;
-+
-+ *lock = ext3_lock_htree(dir, frame->leaf, rwlock);
-+ /* while locking leaf we just found may get splitted
-+ * so, we need another leaf. check this */
-+ if (!dx_check_full_path(frames, &hinfo)) {
-+ ext3_unlock_htree(dir, *lock);
-+ dx_release(frames);
-+ goto repeat;
-+ }
-+
- hash = hinfo.hash;
- do {
-- block = dx_get_block(frame->at);
-+ block = frame->leaf;
- if (!(bh = ext3_bread (NULL,dir, block, 0, err)))
- goto errout;
- de = (struct ext3_dir_entry_2 *) bh->b_data;
-@@ -917,6 +1075,8 @@
- *err = -ENOENT;
- errout:
- dxtrace(printk("%s not found\n", name));
-+ ext3_unlock_htree(dir, *lock);
-+ *lock = NULL;
- dx_release (frames);
- return NULL;
- }
-@@ -927,6 +1087,7 @@
- struct inode * inode;
- struct ext3_dir_entry_2 * de;
- struct buffer_head * bh;
-+ void *lock = NULL;
-
- if (dentry->d_name.len > EXT3_NAME_LEN)
- return ERR_PTR(-ENAMETOOLONG);
-@@ -934,10 +1095,11 @@
- if (ext3_check_for_iopen(dir, dentry))
- return NULL;
-
-- bh = ext3_find_entry(dentry, &de);
-+ bh = ext3_find_entry(dentry, &de, 0, &lock);
- inode = NULL;
- if (bh) {
- unsigned long ino = le32_to_cpu(de->inode);
-+ ext3_unlock_htree(dir, lock);
- brelse (bh);
- inode = iget(dir->i_sb, ino);
-
-@@ -974,7 +1136,8 @@
- unsigned rec_len = 0;
-
- while (count--) {
-- struct ext3_dir_entry_2 *de = (struct ext3_dir_entry_2 *) (from + map->offs);
-+ struct ext3_dir_entry_2 *de =
-+ (struct ext3_dir_entry_2 *) (from + map->offs);
- rec_len = EXT3_DIR_REC_LEN(de->name_len);
- memcpy (to, de, rec_len);
- ((struct ext3_dir_entry_2 *) to)->rec_len = rec_len;
-@@ -987,7 +1150,8 @@
-
- static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size)
- {
-- struct ext3_dir_entry_2 *next, *to, *prev, *de = (struct ext3_dir_entry_2 *) base;
-+ struct ext3_dir_entry_2 *next, *to, *prev;
-+ struct ext3_dir_entry_2 *de = (struct ext3_dir_entry_2 *) base;
- unsigned rec_len = 0;
-
- prev = to = de;
-@@ -1009,7 +1173,8 @@
-
- static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
- struct buffer_head **bh,struct dx_frame *frame,
-- struct dx_hash_info *hinfo, int *error)
-+ struct dx_hash_info *hinfo, void **target,
-+ int *error)
- {
- unsigned blocksize = dir->i_sb->s_blocksize;
- unsigned count, continued;
-@@ -1056,23 +1221,30 @@
- hash2 = map[split].hash;
- continued = hash2 == map[split - 1].hash;
- dxtrace(printk("Split block %i at %x, %i/%i\n",
-- dx_get_block(frame->at), hash2, split, count-split));
--
-+ frame->leaf, hash2, split, count-split));
-+
- /* Fancy dance to stay within two buffers */
- de2 = dx_move_dirents(data1, data2, map + split, count - split);
- de = dx_pack_dirents(data1,blocksize);
- de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
- de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2);
-- dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data1, blocksize, 1));
-- dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data2, blocksize, 1));
-+ dxtrace(dx_show_leaf(hinfo,(struct ext3_dir_entry_2*) data1, blocksize, 1));
-+ dxtrace(dx_show_leaf(hinfo,(struct ext3_dir_entry_2*) data2, blocksize, 1));
-
- /* Which block gets the new entry? */
-+ *target = NULL;
- if (hinfo->hash >= hash2)
- {
- swap(*bh, bh2);
- de = de2;
-- }
-- dx_insert_block (frame, hash2 + continued, newblock);
-+
-+ /* entry will be stored into new block
-+ * we have to lock it before add_dirent_to_buf */
-+ *target = ext3_lock_htree(dir, newblock, 1);
-+ }
-+ dx_lock_bh(frame->bh);
-+ dx_insert_block (dir, frame, hash2 + continued, newblock, frame->curidx);
-+ dx_unlock_bh(frame->bh);
- err = ext3_journal_dirty_metadata (handle, bh2);
- if (err)
- goto journal_error;
-@@ -1146,7 +1318,8 @@
- nlen = EXT3_DIR_REC_LEN(de->name_len);
- rlen = le16_to_cpu(de->rec_len);
- if (de->inode) {
-- struct ext3_dir_entry_2 *de1 = (struct ext3_dir_entry_2 *)((char *)de + nlen);
-+ struct ext3_dir_entry_2 *de1 =
-+ (struct ext3_dir_entry_2 *)((char *)de + nlen);
- de1->rec_len = cpu_to_le16(rlen - nlen);
- de->rec_len = cpu_to_le16(nlen);
- de = de1;
-@@ -1204,7 +1377,8 @@
- unsigned blocksize;
- struct dx_hash_info hinfo;
- u32 block;
--
-+ void *lock, *new_lock;
-+
- blocksize = dir->i_sb->s_blocksize;
- dxtrace(printk("Creating index\n"));
- retval = ext3_journal_get_write_access(handle, bh);
-@@ -1215,7 +1389,6 @@
- }
- root = (struct dx_root *) bh->b_data;
-
-- EXT3_I(dir)->i_flags |= EXT3_INDEX_FL;
- bh2 = ext3_append (handle, dir, &block, &retval);
- if (!(bh2)) {
- brelse(bh);
-@@ -1223,6 +1396,8 @@
- }
- data1 = bh2->b_data;
-
-+ lock = ext3_lock_htree(dir, block, 1);
-+
- /* The 0th block becomes the root, move the dirents out */
- de = (struct ext3_dir_entry_2 *) &root->dotdot;
- de = (struct ext3_dir_entry_2 *) ((char *)de + de->rec_len);
-@@ -1252,13 +1427,25 @@
- frame->entries = entries;
- frame->at = entries;
- frame->bh = bh;
-+ frame->curidx = 0;
-+ frame->leaf = 0;
-+ frame[1].bh = NULL;
- bh = bh2;
-- de = do_split(handle,dir, &bh, frame, &hinfo, &retval);
-+ de = do_split(handle,dir, &bh, frame, &hinfo, &new_lock, &retval);
- dx_release (frames);
- if (!(de))
-- return retval;
-+ goto cleanup;
-+
-+ retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
-+cleanup:
-+ if (new_lock)
-+ ext3_unlock_htree(dir, new_lock);
-+ /* we mark directory indexed in order to
-+ * avoid races while htree being created -bzzz */
-+ EXT3_I(dir)->i_flags |= EXT3_INDEX_FL;
-+ ext3_unlock_htree(dir, lock);
-
-- return add_dirent_to_buf(handle, dentry, inode, de, bh);
-+ return retval;
- }
- #endif
-
-@@ -1287,11 +1474,13 @@
- unsigned blocksize;
- unsigned nlen, rlen;
- u32 block, blocks;
-+ void *lock;
-
- sb = dir->i_sb;
- blocksize = sb->s_blocksize;
- if (!dentry->d_name.len)
- return -EINVAL;
-+repeat:
- #ifdef CONFIG_EXT3_INDEX
- if (is_dx(dir)) {
- retval = ext3_dx_add_entry(handle, dentry, inode);
-@@ -1302,36 +1491,53 @@
- ext3_mark_inode_dirty(handle, dir);
- }
- #endif
-+ lock = ext3_lock_htree(dir, 0, 1);
-+ if (is_dx(dir)) {
-+ /* we got lock for block 0
-+ * probably previous holder of the lock
-+ * created htree -bzzz */
-+ ext3_unlock_htree(dir, lock);
-+ goto repeat;
-+ }
-+
- blocks = dir->i_size >> sb->s_blocksize_bits;
- for (block = 0, offset = 0; block < blocks; block++) {
- bh = ext3_bread(handle, dir, block, 0, &retval);
-- if(!bh)
-+ if(!bh) {
-+ ext3_unlock_htree(dir, lock);
- return retval;
-+ }
- retval = add_dirent_to_buf(handle, dentry, inode, 0, bh);
-- if (retval != -ENOSPC)
-+ if (retval != -ENOSPC) {
-+ ext3_unlock_htree(dir, lock);
- return retval;
-+ }
-
- #ifdef CONFIG_EXT3_INDEX
- if (blocks == 1 && !dx_fallback &&
-- EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX))
-- return make_indexed_dir(handle, dentry, inode, bh);
-+ EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX)) {
-+ retval = make_indexed_dir(handle, dentry, inode, bh);
-+ ext3_unlock_htree(dir, lock);
-+ return retval;
-+ }
- #endif
- brelse(bh);
- }
- bh = ext3_append(handle, dir, &block, &retval);
-- if (!bh)
-+ if (!bh) {
-+ ext3_unlock_htree(dir, lock);
- return retval;
-+ }
- de = (struct ext3_dir_entry_2 *) bh->b_data;
- de->inode = 0;
- de->rec_len = cpu_to_le16(rlen = blocksize);
- nlen = 0;
-- return add_dirent_to_buf(handle, dentry, inode, de, bh);
-+ retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
-+ ext3_unlock_htree(dir, lock);
-+ return retval;
- }
-
- #ifdef CONFIG_EXT3_INDEX
--/*
-- * Returns 0 for success, or a negative error value
-- */
- static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
- struct inode *inode)
- {
-@@ -1343,15 +1549,28 @@
- struct super_block * sb = dir->i_sb;
- struct ext3_dir_entry_2 *de;
- int err;
--
-- frame = dx_probe(dentry, 0, &hinfo, frames, &err);
-+ int curidx;
-+ void *idx_lock, *leaf_lock, *newleaf_lock;
-+
-+repeat:
-+ frame = dx_probe(&dentry->d_name, dir, &hinfo, frames, &err);
- if (!frame)
- return err;
-- entries = frame->entries;
-- at = frame->at;
-
-- if (!(bh = ext3_bread(handle,dir, dx_get_block(frame->at), 0, &err)))
-+ /* we're going to chage leaf, so lock it first */
-+ leaf_lock = ext3_lock_htree(dir, frame->leaf, 1);
-+
-+ /* while locking leaf we just found may get splitted
-+ * so we need to check this */
-+ if (!dx_check_full_path(frames, &hinfo)) {
-+ ext3_unlock_htree(dir, leaf_lock);
-+ dx_release(frames);
-+ goto repeat;
-+ }
-+ if (!(bh = ext3_bread(handle,dir, frame->leaf, 0, &err))) {
-+ printk("can't ext3_bread(%d) = %d\n", (int) frame->leaf, err);
- goto cleanup;
-+ }
-
- BUFFER_TRACE(bh, "get_write_access");
- err = ext3_journal_get_write_access(handle, bh);
-@@ -1364,6 +1583,35 @@
- goto cleanup;
- }
-
-+ /* our leaf has no enough space. hence, we have to
-+ * split it. so lock index for this leaf first */
-+ curidx = frame->curidx;
-+ idx_lock = ext3_lock_htree(dir, curidx, 1);
-+
-+ /* now check did path get changed? */
-+ dx_release(frames);
-+
-+ frame = dx_probe(&dentry->d_name, dentry->d_parent->d_inode,
-+ &hinfo, frames, &err);
-+ if (!frame) {
-+ /* FIXME: error handling here */
-+ brelse(bh);
-+ ext3_unlock_htree(dir, idx_lock);
-+ return err;
-+ }
-+
-+ if (frame->curidx != curidx) {
-+ /* path has been changed. we have to drop old lock
-+ * and repeat */
-+ brelse(bh);
-+ ext3_unlock_htree(dir, idx_lock);
-+ ext3_unlock_htree(dir, leaf_lock);
-+ dx_release(frames);
-+ goto repeat;
-+ }
-+ entries = frame->entries;
-+ at = frame->at;
-+
- /* Block full, should compress but for now just split */
- dxtrace(printk("using %u of %u node entries\n",
- dx_get_count(entries), dx_get_limit(entries)));
-@@ -1375,7 +1623,8 @@
- struct dx_entry *entries2;
- struct dx_node *node2;
- struct buffer_head *bh2;
--
-+ void *nb_lock;
-+
- if (levels && (dx_get_count(frames->entries) ==
- dx_get_limit(frames->entries))) {
- ext3_warning(sb, __FUNCTION__,
-@@ -1386,6 +1635,7 @@
- bh2 = ext3_append (handle, dir, &newblock, &err);
- if (!(bh2))
- goto cleanup;
-+ nb_lock = ext3_lock_htree(dir, newblock, 1);
- node2 = (struct dx_node *)(bh2->b_data);
- entries2 = node2->entries;
- node2->fake.rec_len = cpu_to_le16(sb->s_blocksize);
-@@ -1397,27 +1647,73 @@
- if (levels) {
- unsigned icount1 = icount/2, icount2 = icount - icount1;
- unsigned hash2 = dx_get_hash(entries + icount1);
-+ void *ri_lock;
-+
-+ /* we have to protect root htree index against
-+ * another dx_add_entry() which would want to
-+ * split it too -bzzz */
-+ ri_lock = ext3_lock_htree(dir, 0, 1);
-+
-+ /* as root index block blocked we must repeat
-+ * searching for current position of our 2nd index -bzzz */
-+ dx_lock_bh(frame->bh);
-+ frames->at = dx_find_position(frames->entries, hinfo.hash);
-+ dx_unlock_bh(frame->bh);
-+
- dxtrace(printk("Split index %i/%i\n", icount1, icount2));
--
-- BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */
-+
-+ BUFFER_TRACE(frame->bh, "get_write_access");
- err = ext3_journal_get_write_access(handle,
- frames[0].bh);
- if (err)
- goto journal_error;
--
-+
-+ /* copy index into new one */
- memcpy ((char *) entries2, (char *) (entries + icount1),
- icount2 * sizeof(struct dx_entry));
-- dx_set_count (entries, icount1);
- dx_set_count (entries2, icount2);
- dx_set_limit (entries2, dx_node_limit(dir));
-
- /* Which index block gets the new entry? */
- if (at - entries >= icount1) {
-+ /* unlock index we won't use */
-+ ext3_unlock_htree(dir, idx_lock);
-+ idx_lock = nb_lock;
- frame->at = at = at - entries - icount1 + entries2;
-- frame->entries = entries = entries2;
-+ frame->entries = entries2;
-+ frame->curidx = curidx = newblock;
- swap(frame->bh, bh2);
-+ } else {
-+ /* we'll use old index,so new one may be freed */
-+ ext3_unlock_htree(dir, nb_lock);
- }
-- dx_insert_block (frames + 0, hash2, newblock);
-+
-+ /* NOTE: very subtle piece of code
-+ * competing dx_probe() may find 2nd level index in root
-+ * index, then we insert new index here and set new count
-+ * in that 2nd level index. so, dx_probe() may see 2nd
-+ * level index w/o hash it looks for. the solution is
-+ * to check root index after we locked just founded 2nd
-+ * level index -bzzz */
-+ dx_lock_bh(frames[0].bh);
-+ dx_insert_block (dir, frames + 0, hash2, newblock, 0);
-+ dx_unlock_bh(frames[0].bh);
-+
-+ /* now old and new 2nd level index blocks contain
-+ * all pointers, so dx_probe() may find it in the both.
-+ * it's OK -bzzz */
-+
-+ dx_lock_bh(frame->bh);
-+ dx_set_count(entries, icount1);
-+ dx_unlock_bh(frame->bh);
-+
-+ /* now old 2nd level index block points to first half
-+ * of leafs. it's importand that dx_probe() must
-+ * check root index block for changes under
-+ * dx_lock_bh(frame->bh) -bzzz */
-+
-+ ext3_unlock_htree(dir, ri_lock);
-+
- dxtrace(dx_show_index ("node", frames[1].entries));
- dxtrace(dx_show_index ("node",
- ((struct dx_node *) bh2->b_data)->entries));
-@@ -1426,38 +1722,61 @@
- goto journal_error;
- brelse (bh2);
- } else {
-+ unsigned long leaf = frame->leaf;
-+
- dxtrace(printk("Creating second level index...\n"));
- memcpy((char *) entries2, (char *) entries,
- icount * sizeof(struct dx_entry));
- dx_set_limit(entries2, dx_node_limit(dir));
-
- /* Set up root */
-+ dx_lock_bh(frames[0].bh);
- dx_set_count(entries, 1);
- dx_set_block(entries + 0, newblock);
- ((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels = 1;
-+ dx_unlock_bh(frames[0].bh);
-
- /* Add new access path frame */
- frame = frames + 1;
- frame->at = at = at - entries + entries2;
- frame->entries = entries = entries2;
- frame->bh = bh2;
-+ frame->curidx = newblock;
-+ frame->leaf = leaf;
- err = ext3_journal_get_write_access(handle,
- frame->bh);
- if (err)
- goto journal_error;
-+
-+ /* first level index was root. it's already initialized */
-+ /* we my unlock it now */
-+ ext3_unlock_htree(dir, idx_lock);
-+
-+ /* current index is just created 2nd level index */
-+ curidx = newblock;
-+ idx_lock = nb_lock;
- }
- ext3_journal_dirty_metadata(handle, frames[0].bh);
- }
-- de = do_split(handle, dir, &bh, frame, &hinfo, &err);
-+ de = do_split(handle, dir, &bh, frame, &hinfo, &newleaf_lock, &err);
- if (!de)
- goto cleanup;
-+
-+ /* index splitted */
-+ ext3_unlock_htree(dir, idx_lock);
-+
- err = add_dirent_to_buf(handle, dentry, inode, de, bh);
-+
-+ if (newleaf_lock)
-+ ext3_unlock_htree(dir, newleaf_lock);
-+
- bh = 0;
- goto cleanup;
-
- journal_error:
- ext3_std_error(dir->i_sb, err);
- cleanup:
-+ ext3_unlock_htree(dir, leaf_lock);
- if (bh)
- brelse(bh);
- dx_release(frames);
-@@ -1901,6 +2220,7 @@
- struct buffer_head * bh;
- struct ext3_dir_entry_2 * de;
- handle_t *handle;
-+ void *lock;
-
- handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
- if (IS_ERR(handle)) {
-@@ -1908,7 +2228,7 @@
- }
-
- retval = -ENOENT;
-- bh = ext3_find_entry (dentry, &de);
-+ bh = ext3_find_entry (dentry, &de, 1, &lock);
- if (!bh)
- goto end_rmdir;
-
-@@ -1919,14 +2239,19 @@
- DQUOT_INIT(inode);
-
- retval = -EIO;
-- if (le32_to_cpu(de->inode) != inode->i_ino)
-+ if (le32_to_cpu(de->inode) != inode->i_ino) {
-+ ext3_unlock_htree(dir, lock);
- goto end_rmdir;
-+ }
-
- retval = -ENOTEMPTY;
-- if (!empty_dir (inode))
-+ if (!empty_dir (inode)) {
-+ ext3_unlock_htree(dir, lock);
- goto end_rmdir;
-+ }
-
- retval = ext3_delete_entry(handle, dir, de, bh);
-+ ext3_unlock_htree(dir, lock);
- if (retval)
- goto end_rmdir;
- if (inode->i_nlink != 2)
-@@ -1985,6 +2310,7 @@
- struct buffer_head * bh;
- struct ext3_dir_entry_2 * de;
- handle_t *handle;
-+ void *lock;
-
- handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
- if (IS_ERR(handle)) {
-@@ -1995,7 +2321,7 @@
- handle->h_sync = 1;
-
- retval = -ENOENT;
-- bh = ext3_find_entry (dentry, &de);
-+ bh = ext3_find_entry (dentry, &de, 1, &lock);
- if (!bh)
- goto end_unlink;
-
-@@ -2003,8 +2329,10 @@
- DQUOT_INIT(inode);
-
- retval = -EIO;
-- if (le32_to_cpu(de->inode) != inode->i_ino)
-+ if (le32_to_cpu(de->inode) != inode->i_ino) {
-+ ext3_unlock_htree(dir, lock);
- goto end_unlink;
-+ }
-
- if (!inode->i_nlink) {
- ext3_warning (inode->i_sb, "ext3_unlink",
-@@ -2013,6 +2341,7 @@
- inode->i_nlink = 1;
- }
- retval = ext3_delete_entry(handle, dir, de, bh);
-+ ext3_unlock_htree(dir, lock);
- if (retval)
- goto end_unlink;
- dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-@@ -2151,6 +2480,7 @@
- struct buffer_head * old_bh, * new_bh, * dir_bh;
- struct ext3_dir_entry_2 * old_de, * new_de;
- int retval;
-+ void *lock1 = NULL, *lock2 = NULL, *lock3 = NULL;
-
- old_bh = new_bh = dir_bh = NULL;
-
-@@ -2163,7 +2493,10 @@
- if (IS_SYNC(old_dir) || IS_SYNC(new_dir))
- handle->h_sync = 1;
-
-- old_bh = ext3_find_entry (old_dentry, &old_de);
-+ if (old_dentry->d_parent == new_dentry->d_parent)
-+ down(&EXT3_I(old_dentry->d_parent->d_inode)->i_rename_sem);
-+
-+ old_bh = ext3_find_entry (old_dentry, &old_de, 1, &lock1 /* FIXME */);
- /*
- * Check for inode number is _not_ due to possible IO errors.
- * We might rmdir the source, keep it as pwd of some process
-@@ -2176,7 +2509,7 @@
- goto end_rename;
-
- new_inode = new_dentry->d_inode;
-- new_bh = ext3_find_entry (new_dentry, &new_de);
-+ new_bh = ext3_find_entry (new_dentry, &new_de, 1, &lock2 /* FIXME */);
- if (new_bh) {
- if (!new_inode) {
- brelse (new_bh);
-@@ -2239,7 +2572,7 @@
- struct buffer_head *old_bh2;
- struct ext3_dir_entry_2 *old_de2;
-
-- old_bh2 = ext3_find_entry(old_dentry, &old_de2);
-+ old_bh2 = ext3_find_entry(old_dentry, &old_de2, 1, &lock3 /* FIXME */);
- if (old_bh2) {
- retval = ext3_delete_entry(handle, old_dir,
- old_de2, old_bh2);
-@@ -2282,6 +2615,14 @@
- retval = 0;
-
- end_rename:
-+ if (lock1)
-+ ext3_unlock_htree(old_dentry->d_parent->d_inode, lock1);
-+ if (lock2)
-+ ext3_unlock_htree(new_dentry->d_parent->d_inode, lock2);
-+ if (lock3)
-+ ext3_unlock_htree(old_dentry->d_parent->d_inode, lock3);
-+ if (old_dentry->d_parent == new_dentry->d_parent)
-+ up(&EXT3_I(old_dentry->d_parent->d_inode)->i_rename_sem);
- brelse (dir_bh);
- brelse (old_bh);
- brelse (new_bh);
-@@ -2290,6 +2631,29 @@
- }
-
- /*
-+ * this locking primitives are used to protect parts
-+ * of dir's htree. protection unit is block: leaf or index
-+ */
-+static inline void *ext3_lock_htree(struct inode *dir,
-+ unsigned long value, int rwlock)
-+{
-+ void *lock;
-+
-+ if (!test_opt(dir->i_sb, PDIROPS))
-+ return NULL;
-+ lock = dynlock_lock(&EXT3_I(dir)->i_htree_lock, value, 1, GFP_KERNEL);
-+ return lock;
-+}
-+
-+static inline void ext3_unlock_htree(struct inode *dir,
-+ void *lock)
-+{
-+ if (!test_opt(dir->i_sb, PDIROPS) || !lock)
-+ return;
-+ dynlock_unlock(&EXT3_I(dir)->i_htree_lock, lock);
-+}
-+
-+/*
- * directories can handle most operations...
- */
- struct inode_operations ext3_dir_inode_operations = {
-Index: linux-2.4.24/fs/ext3/super.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/super.c 2004-04-01 20:22:17.000000000 +0400
-+++ linux-2.4.24/fs/ext3/super.c 2004-04-01 20:24:48.000000000 +0400
-@@ -702,6 +702,8 @@
- return 0;
- }
- }
-+ else if (!strcmp (this_char, "pdirops"))
-+ set_opt (sbi->s_mount_opt, PDIROPS);
- else if (!strcmp (this_char, "grpid") ||
- !strcmp (this_char, "bsdgroups"))
- set_opt (*mount_options, GRPID);
-@@ -728,6 +730,9 @@
- if (want_numeric(value, "sb", sb_block))
- return 0;
- }
-+ else if (!strcmp (this_char, "pdirops")) {
-+ set_opt (sbi->s_mount_opt, PDIROPS);
-+ }
- #ifdef CONFIG_JBD_DEBUG
- else if (!strcmp (this_char, "ro-after")) {
- unsigned long v;
-@@ -891,6 +896,10 @@
- ext3_check_inodes_bitmap (sb);
- }
- #endif
-+#ifdef S_PDIROPS
-+ if (test_opt (sb, PDIROPS))
-+ sb->s_flags |= S_PDIROPS;
-+#endif
- setup_ro_after(sb);
- return res;
- }
-@@ -1393,6 +1402,11 @@
- test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":
- "writeback");
-
-+ if (test_opt(sb, PDIROPS)) {
-+ printk (KERN_INFO "EXT3-fs: mounted filesystem with parallel dirops\n");
-+ sb->s_flags |= S_PDIROPS;
-+ }
-+
- return sb;
-
- failed_mount3:
-Index: linux-2.4.24/fs/ext3/inode.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/inode.c 2004-04-01 20:22:18.000000000 +0400
-+++ linux-2.4.24/fs/ext3/inode.c 2004-04-01 20:24:48.000000000 +0400
-@@ -2239,6 +2239,9 @@
- } else if (S_ISDIR(inode->i_mode)) {
- inode->i_op = &ext3_dir_inode_operations;
- inode->i_fop = &ext3_dir_operations;
-+ dynlock_init(&EXT3_I(inode)->i_htree_lock);
-+ sema_init(&EXT3_I(inode)->i_rename_sem, 1);
-+ sema_init(&EXT3_I(inode)->i_append_sem, 1);
- } else if (S_ISLNK(inode->i_mode)) {
- if (ext3_inode_is_fast_symlink(inode))
- inode->i_op = &ext3_fast_symlink_inode_operations;
-Index: linux-2.4.24/fs/ext3/ialloc.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/ialloc.c 2004-04-01 20:22:17.000000000 +0400
-+++ linux-2.4.24/fs/ext3/ialloc.c 2004-04-01 20:24:48.000000000 +0400
-@@ -606,6 +606,9 @@
- return ERR_PTR(-EDQUOT);
- }
- ext3_debug ("allocating inode %lu\n", inode->i_ino);
-+ dynlock_init(&EXT3_I(inode)->i_htree_lock);
-+ sema_init(&EXT3_I(inode)->i_rename_sem, 1);
-+ sema_init(&EXT3_I(inode)->i_append_sem, 1);
- return inode;
-
- fail:
-Index: linux-2.4.24/include/linux/ext3_fs.h
-===================================================================
---- linux-2.4.24.orig/include/linux/ext3_fs.h 2004-04-01 20:22:17.000000000 +0400
-+++ linux-2.4.24/include/linux/ext3_fs.h 2004-04-01 20:24:48.000000000 +0400
-@@ -308,6 +308,7 @@
- /*
- * Mount flags
- */
-+#define EXT3_MOUNT_PDIROPS 0x800000/* Parallel dir operations */
- #define EXT3_MOUNT_CHECK 0x0001 /* Do mount-time checks */
- #define EXT3_MOUNT_GRPID 0x0004 /* Create files with directory's group */
- #define EXT3_MOUNT_DEBUG 0x0008 /* Some debugging messages */
-Index: linux-2.4.24/include/linux/ext3_fs_i.h
-===================================================================
---- linux-2.4.24.orig/include/linux/ext3_fs_i.h 2004-04-01 20:22:17.000000000 +0400
-+++ linux-2.4.24/include/linux/ext3_fs_i.h 2004-04-01 20:24:48.000000000 +0400
-@@ -17,6 +17,7 @@
- #define _LINUX_EXT3_FS_I
-
- #include <linux/rwsem.h>
-+#include <linux/dynlocks.h>
-
- /*
- * second extended file system inode data in memory
-@@ -76,6 +77,11 @@
- * by other means, so we have truncate_sem.
- */
- struct rw_semaphore truncate_sem;
-+
-+ /* following fields for parallel directory operations -bzzz */
-+ struct dynlock i_htree_lock;
-+ struct semaphore i_append_sem;
-+ struct semaphore i_rename_sem;
- };
-
- #endif /* _LINUX_EXT3_FS_I */
+++ /dev/null
- fs/ext3/namei.c | 31 +++++++++++++++++++++++++++++++
- include/linux/fs.h | 1 +
- 2 files changed, 32 insertions(+)
-
-Index: lum/include/linux/fs.h
-===================================================================
---- lum.orig/include/linux/fs.h 2004-06-07 17:52:41.000000000 -0400
-+++ lum/include/linux/fs.h 2004-06-07 17:56:55.000000000 -0400
-@@ -904,6 +904,7 @@
- int (*create) (struct inode *,struct dentry *,int);
- int (*create_it) (struct inode *,struct dentry *,int, struct lookup_intent *);
- struct dentry * (*lookup) (struct inode *,struct dentry *);
-+ int (*lookup_raw) (struct inode *, const char *, int, ino_t *);
- struct dentry * (*lookup_it) (struct inode *,struct dentry *, struct nameidata *, struct lookup_intent *, int flags);
- int (*link) (struct dentry *,struct inode *,struct dentry *);
- int (*link_raw) (struct nameidata *,struct nameidata *);
-Index: lum/fs/ext3/namei.c
-===================================================================
---- lum.orig/fs/ext3/namei.c 2004-06-07 17:52:41.000000000 -0400
-+++ lum/fs/ext3/namei.c 2004-06-07 17:56:31.000000000 -0400
-@@ -1128,6 +1128,36 @@
- return iopen_connect_dentry(dentry, inode, 1);
- }
-
-+static int ext3_lookup_raw(struct inode *dir, const char *name,
-+ int len, ino_t *data)
-+{
-+ struct ext3_dir_entry_2 *de;
-+ struct buffer_head *bh;
-+ struct dentry parent;
-+ struct dentry dentry;
-+ void *lock = NULL;
-+
-+ if (len > EXT3_NAME_LEN)
-+ return -ENAMETOOLONG;
-+
-+ parent.d_inode = dir;
-+ dentry.d_parent = &parent;
-+ dentry.d_name.name = name;
-+ dentry.d_name.len = len;
-+
-+ bh = ext3_find_entry(&dentry, &de, 0, &lock);
-+ if (bh) {
-+ unsigned long ino = le32_to_cpu(de->inode);
-+ ext3_unlock_htree(dir, lock);
-+ brelse (bh);
-+ if (data)
-+ *data = ino;
-+ return 0; /* found name */
-+ }
-+
-+ return -ENOENT;
-+}
-+
- #define S_SHIFT 12
- static unsigned char ext3_type_by_mode[S_IFMT >> S_SHIFT] = {
- [S_IFREG >> S_SHIFT] EXT3_FT_REG_FILE,
-@@ -2772,6 +2802,7 @@
- struct inode_operations ext3_dir_inode_operations = {
- create: ext3_create, /* BKL held */
- lookup: ext3_lookup, /* BKL held */
-+ lookup_raw: ext3_lookup_raw, /* BKL held */
- link: ext3_link, /* BKL held */
- unlink: ext3_unlink, /* BKL held */
- symlink: ext3_symlink, /* BKL held */
+++ /dev/null
- fs/ext3/ext3-exports.c | 9 ++++-
- fs/ext3/inode.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++
- 2 files changed, 89 insertions(+), 1 deletion(-)
-
---- linux/fs/ext3/inode.c~ext3-san-2.4.20-hp Tue Apr 29 11:01:52 2003
-+++ linux-mmonroe/fs/ext3/inode.c Tue Apr 29 11:01:53 2003
-@@ -2734,3 +2734,84 @@ int ext3_change_inode_journal_flag(struc
- * here, in ext3_aops_journal_start() to ensure that the forthcoming "see if we
- * need to extend" test in ext3_prepare_write() succeeds.
- */
-+
-+/* for each block: 1 ind + 1 dind + 1 tind
-+ * for each block: 3 bitmap blocks
-+ * for each block: 3 group descriptor blocks
-+ * i inode block
-+ * 1 superblock
-+ * 2 * EXT3_SINGLEDATA_TRANS_BLOCKS for the quote files
-+ * ((1+1+1) * 3 * nblocks) + 1 + 1 + 2 * EXT3_SINGLEDATA_TRANS_BLOCKS
-+ *
-+ * XXX assuming:
-+ * (1) fs logic block size == page size
-+ * (2) ext3 in writeback mode
-+ */
-+static inline int ext3_san_write_trans_blocks(int nblocks)
-+{
-+ int ret;
-+
-+ ret = (1 + 1 + 1) * 3 * nblocks + 1 + 1;
-+
-+#ifdef CONFIG_QUOTA
-+ ret += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS;
-+#endif
-+
-+ return ret;
-+}
-+
-+/* Alloc blocks for an inode, while don't create any buffer/page
-+ * for data I/O; set the inode size if file is extended.
-+ *
-+ * @inode: target inode
-+ * @blocks: array of logic block number
-+ * @nblocks: how many blocks need be alloced
-+ * @newsize: new filesize we should set
-+ *
-+ * return: 0 success, otherwise failed
-+ * (*blocks) contains physical block number alloced
-+ *
-+ * XXX this assume the fs block size == page size
-+ */
-+int ext3_prep_san_write(struct inode *inode, long *blocks,
-+ int nblocks, loff_t newsize)
-+{
-+ handle_t *handle;
-+ struct buffer_head bh_tmp;
-+ int needed_blocks;
-+ int i, ret = 0, ret2;
-+
-+ needed_blocks = ext3_san_write_trans_blocks(nblocks);
-+
-+ lock_kernel();
-+ handle = ext3_journal_start(inode, needed_blocks);
-+ if (IS_ERR(handle)) {
-+ unlock_kernel();
-+ return PTR_ERR(handle);
-+ }
-+ unlock_kernel();
-+
-+ /* alloc blocks one by one */
-+ for (i = 0; i < nblocks; i++) {
-+ ret = ext3_get_block_handle(handle, inode, blocks[i],
-+ &bh_tmp, 1);
-+ if (ret)
-+ break;
-+
-+ blocks[i] = bh_tmp.b_blocknr;
-+ }
-+
-+ /* set inode size if needed */
-+ if (!ret && (newsize > inode->i_size)) {
-+ inode->i_size = newsize;
-+ ext3_mark_inode_dirty(handle, inode);
-+ }
-+
-+ lock_kernel();
-+ ret2 = ext3_journal_stop(handle, inode);
-+ unlock_kernel();
-+
-+ if (!ret)
-+ ret = ret2;
-+ return ret;
-+}
---- linux/fs/ext3/ext3-exports.c~ext3-san-2.4.20-hp Tue Apr 29 11:01:51 2003
-+++ linux-mmonroe/fs/ext3/ext3-exports.c Tue Apr 29 11:07:19 2003
-@@ -1,9 +1,15 @@
- #include <linux/config.h>
- #include <linux/module.h>
--#include <linux/ext3_fs.h>
-+#include <linux/fs.h>
-+#include <linux/locks.h>
-+#include <linux/slab.h>
- #include <linux/ext3_jbd.h>
-+#include <linux/ext3_fs.h>
- #include <linux/ext3_xattr.h>
-
-+int ext3_prep_san_write(struct inode *inode, long *blocks,
-+ int nblocks, loff_t newsize);
-+
- EXPORT_SYMBOL(ext3_force_commit);
- EXPORT_SYMBOL(ext3_bread);
- EXPORT_SYMBOL(ext3_xattr_register);
-@@ -11,3 +17,4 @@ EXPORT_SYMBOL(ext3_xattr_unregister);
- EXPORT_SYMBOL(ext3_xattr_get);
- EXPORT_SYMBOL(ext3_xattr_list);
- EXPORT_SYMBOL(ext3_xattr_set);
-+EXPORT_SYMBOL(ext3_prep_san_write);
-
-_
+++ /dev/null
---- lum/fs/ext3/inode.c~ 2004-01-30 16:47:12.000000000 -0800
-+++ lum/fs/ext3/inode.c 2004-01-30 16:46:14.000000000 -0800
-@@ -1485,6 +1485,7 @@
- if (ext3_should_order_data(inode))
- err = ext3_journal_dirty_data(handle, bh, 0);
- __mark_buffer_dirty(bh);
-+ buffer_insert_inode_data_queue(bh, inode);
- }
-
- unlock:
+++ /dev/null
- fs/ext3/xattr.c | 12 +++++-
- fs/ext3/xattr_trusted.c | 86 +++++++++++++++++++++++++++++++++++++++++++++
- include/linux/ext3_xattr.h | 6 +++
- 3 files changed, 102 insertions(+), 2 deletions(-)
-
-Index: linux-2.4.20/fs/ext3/xattr.c
-===================================================================
---- linux-2.4.20.orig/fs/ext3/xattr.c 2003-10-22 02:29:40.000000000 +0400
-+++ linux-2.4.20/fs/ext3/xattr.c 2003-10-24 01:03:22.000000000 +0400
-@@ -1771,18 +1771,25 @@
- int __init
- init_ext3_xattr(void)
- {
-+ int error;
-+
- ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL,
- sizeof(struct mb_cache_entry) +
- sizeof(struct mb_cache_entry_index), 1, 61);
- if (!ext3_xattr_cache)
- return -ENOMEM;
-
-- return 0;
-+ error = init_ext3_xattr_trusted();
-+ if (error)
-+ mb_cache_destroy(ext3_xattr_cache);
-+
-+ return error;
- }
-
- void
- exit_ext3_xattr(void)
- {
-+ exit_ext3_xattr_trusted();
- if (ext3_xattr_cache)
- mb_cache_destroy(ext3_xattr_cache);
- ext3_xattr_cache = NULL;
-@@ -1793,12 +1800,13 @@
- int __init
- init_ext3_xattr(void)
- {
-- return 0;
-+ return init_ext3_xattr_trusted();
- }
-
- void
- exit_ext3_xattr(void)
- {
-+ exit_ext3_xattr_trusted();
- }
-
- #endif /* CONFIG_EXT3_FS_XATTR_SHARING */
-Index: linux-2.4.20/fs/ext3/xattr_trusted.c
-===================================================================
---- linux-2.4.20.orig/fs/ext3/xattr_trusted.c 2003-10-24 01:03:22.000000000 +0400
-+++ linux-2.4.20/fs/ext3/xattr_trusted.c 2003-10-24 01:03:22.000000000 +0400
-@@ -0,0 +1,86 @@
-+/*
-+ * linux/fs/ext3/xattr_trusted.c
-+ * Handler for trusted extended attributes.
-+ *
-+ * Copyright (C) 2003 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/string.h>
-+#include <linux/fs.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/ext3_fs.h>
-+#include <linux/ext3_xattr.h>
-+
-+#define XATTR_TRUSTED_PREFIX "trusted."
-+
-+static size_t
-+ext3_xattr_trusted_list(char *list, struct inode *inode,
-+ const char *name, int name_len)
-+{
-+ const int prefix_len = sizeof(XATTR_TRUSTED_PREFIX)-1;
-+
-+ if (!capable(CAP_SYS_ADMIN))
-+ return 0;
-+
-+ if (list) {
-+ memcpy(list, XATTR_TRUSTED_PREFIX, prefix_len);
-+ memcpy(list+prefix_len, name, name_len);
-+ list[prefix_len + name_len] = '\0';
-+ }
-+ return prefix_len + name_len + 1;
-+}
-+
-+static int
-+ext3_xattr_trusted_get(struct inode *inode, const char *name,
-+ void *buffer, size_t size)
-+{
-+ if (strcmp(name, "") == 0)
-+ return -EINVAL;
-+ if (!capable(CAP_SYS_ADMIN))
-+ return -EPERM;
-+ return ext3_xattr_get(inode, EXT3_XATTR_INDEX_TRUSTED, name,
-+ buffer, size);
-+}
-+
-+static int
-+ext3_xattr_trusted_set(struct inode *inode, const char *name,
-+ const void *value, size_t size, int flags)
-+{
-+ handle_t *handle;
-+ int error;
-+
-+ if (strcmp(name, "") == 0)
-+ return -EINVAL;
-+ if (!capable(CAP_SYS_ADMIN))
-+ return -EPERM;
-+ handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
-+ if (IS_ERR(handle))
-+ return PTR_ERR(handle);
-+ error = ext3_xattr_set(handle, inode, EXT3_XATTR_INDEX_TRUSTED, name,
-+ value, size, flags);
-+ ext3_journal_stop(handle, inode);
-+
-+ return error;
-+}
-+
-+struct ext3_xattr_handler ext3_xattr_trusted_handler = {
-+ .prefix = XATTR_TRUSTED_PREFIX,
-+ .list = ext3_xattr_trusted_list,
-+ .get = ext3_xattr_trusted_get,
-+ .set = ext3_xattr_trusted_set,
-+};
-+
-+int __init
-+init_ext3_xattr_trusted(void)
-+{
-+ return ext3_xattr_register(EXT3_XATTR_INDEX_TRUSTED,
-+ &ext3_xattr_trusted_handler);
-+}
-+
-+void
-+exit_ext3_xattr_trusted(void)
-+{
-+ ext3_xattr_unregister(EXT3_XATTR_INDEX_TRUSTED,
-+ &ext3_xattr_trusted_handler);
-+}
-Index: linux-2.4.20/include/linux/ext3_xattr.h
-===================================================================
---- linux-2.4.20.orig/include/linux/ext3_xattr.h 2003-10-22 02:29:39.000000000 +0400
-+++ linux-2.4.20/include/linux/ext3_xattr.h 2003-10-24 01:03:22.000000000 +0400
-@@ -21,6 +21,9 @@
- #define EXT3_XATTR_INDEX_USER 1
- #define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS 2
- #define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT 3
-+#define EXT3_XATTR_INDEX_TRUSTED 4
-+#define EXT3_XATTR_INDEX_LUSTRE 5
-+#define EXT3_XATTR_INDEX_SECURITY 6
-
- struct ext3_xattr_header {
- __u32 h_magic; /* magic number for identification */
-@@ -84,6 +87,9 @@
- extern int init_ext3_xattr(void) __init;
- extern void exit_ext3_xattr(void);
-
-+extern int init_ext3_xattr_trusted(void) __init;
-+extern void exit_ext3_xattr_trusted(void);
-+
- # else /* CONFIG_EXT3_FS_XATTR */
- # define ext3_setxattr NULL
- # define ext3_getxattr NULL
-Index: linux-2.4.20/fs/ext3/Makefile
-===================================================================
---- linux-2.4.20.orig/fs/ext3/Makefile 2003-10-22 02:29:40.000000000 +0400
-+++ linux-2.4.20/fs/ext3/Makefile 2003-10-24 01:03:47.000000000 +0400
-@@ -12,7 +12,8 @@
- export-objs := ext3-exports.o
-
- obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
-- ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o
-+ ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o \
-+ xattr_trusted.o
- obj-m := $(O_TARGET)
-
- export-objs += xattr.o
+++ /dev/null
-Index: linux-2.4.20/fs/ext3/xattr.c
-===================================================================
---- linux-2.4.20.orig/fs/ext3/xattr.c 2003-11-13 10:59:33.000000000 +0800
-+++ linux-2.4.20/fs/ext3/xattr.c 2003-11-25 21:16:51.000000000 +0800
-@@ -1293,9 +1293,10 @@
- goto cleanup;
- memcpy(header, HDR(bh), bh->b_size);
- header->h_refcount = cpu_to_le32(1);
-- offset = (char *)header - bh->b_data;
-- here = ENTRY((char *)here + offset);
-- last = ENTRY((char *)last + offset);
-+ offset = (char *)here - bh->b_data;
-+ here = ENTRY((char *)header + offset);
-+ offset = (char *)last - bh->b_data;
-+ last = ENTRY((char *)header + offset);
- }
- } else {
- /* Allocate a buffer where we construct the new block. */
+++ /dev/null
- fs/ext3/ialloc.c | 40 ++++++++++++++++++++++++++++++++++++++--
- fs/ext3/inode.c | 2 +-
- fs/ext3/ioctl.c | 25 +++++++++++++++++++++++++
- fs/ext3/namei.c | 21 +++++++++++++++++----
- include/linux/dcache.h | 5 +++++
- include/linux/ext3_fs.h | 5 ++++-
- 6 files changed, 90 insertions(+), 8 deletions(-)
-
-Index: linux-2.4.24/fs/ext3/namei.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/namei.c 2004-05-19 13:58:43.000000000 +0400
-+++ linux-2.4.24/fs/ext3/namei.c 2004-05-21 18:26:43.000000000 +0400
-@@ -1533,6 +1533,23 @@
- return err;
- }
-
-+static struct inode * ext3_new_inode_wantedi(handle_t *handle, struct inode *dir,
-+ int mode, struct dentry *dentry)
-+{
-+ struct dentry_params *param = (struct dentry_params *) dentry->d_fsdata;
-+ unsigned long inum = 0;
-+ struct inode *inode;
-+
-+ if (param != NULL)
-+ inum = param->p_inum;
-+ inode = ext3_new_inode(handle, dir, mode, inum);
-+ if (inode && param && inum && param->p_generation) {
-+ inode->i_generation = param->p_generation;
-+ ext3_mark_inode_dirty(handle, inode);
-+ }
-+ return inode;
-+}
-+
- /*
- * By the time this is called, we already have created
- * the directory cache entry for the new file, but it
-@@ -1556,7 +1573,7 @@
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-
-- inode = ext3_new_inode (handle, dir, mode);
-+ inode = ext3_new_inode_wantedi (handle, dir, mode, dentry);
- err = PTR_ERR(inode);
- if (!IS_ERR(inode)) {
- inode->i_op = &ext3_file_inode_operations;
-@@ -1584,7 +1601,7 @@
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-
-- inode = ext3_new_inode (handle, dir, mode);
-+ inode = ext3_new_inode_wantedi (handle, dir, mode, dentry);
- err = PTR_ERR(inode);
- if (!IS_ERR(inode)) {
- init_special_inode(inode, mode, rdev);
-@@ -1614,7 +1631,7 @@
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-
-- inode = ext3_new_inode (handle, dir, S_IFDIR | mode);
-+ inode = ext3_new_inode_wantedi (handle, dir, S_IFDIR | mode, dentry);
- err = PTR_ERR(inode);
- if (IS_ERR(inode))
- goto out_stop;
-@@ -2041,7 +2058,7 @@
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-
-- inode = ext3_new_inode (handle, dir, S_IFLNK|S_IRWXUGO);
-+ inode = ext3_new_inode_wantedi (handle, dir, S_IFLNK|S_IRWXUGO, dentry);
- err = PTR_ERR(inode);
- if (IS_ERR(inode))
- goto out_stop;
-Index: linux-2.4.24/fs/ext3/ialloc.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/ialloc.c 2004-05-19 13:58:43.000000000 +0400
-+++ linux-2.4.24/fs/ext3/ialloc.c 2004-05-19 13:58:43.000000000 +0400
-@@ -330,7 +330,8 @@
- * group to find a free inode.
- */
- struct inode * ext3_new_inode (handle_t *handle,
-- const struct inode * dir, int mode)
-+ const struct inode * dir, int mode,
-+ unsigned long goal)
- {
- struct super_block * sb;
- struct buffer_head * bh;
-@@ -355,7 +356,41 @@
- init_rwsem(&inode->u.ext3_i.truncate_sem);
-
- lock_super (sb);
-- es = sb->u.ext3_sb.s_es;
-+ es = EXT3_SB(sb)->s_es;
-+
-+ if (goal) {
-+ i = (goal - 1) / EXT3_INODES_PER_GROUP(sb);
-+ j = (goal - 1) % EXT3_INODES_PER_GROUP(sb);
-+ gdp = ext3_get_group_desc(sb, i, &bh2);
-+
-+ bitmap_nr = load_inode_bitmap (sb, i);
-+ if (bitmap_nr < 0) {
-+ err = bitmap_nr;
-+ goto fail;
-+ }
-+
-+ bh = EXT3_SB(sb)->s_inode_bitmap[bitmap_nr];
-+
-+ BUFFER_TRACE(bh, "get_write_access");
-+ err = ext3_journal_get_write_access(handle, bh);
-+ if (err) goto fail;
-+
-+ if (ext3_set_bit(j, bh->b_data)) {
-+ printk(KERN_ERR "goal inode %lu unavailable\n", goal);
-+ /* Oh well, we tried. */
-+ goto repeat;
-+ }
-+
-+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
-+ err = ext3_journal_dirty_metadata(handle, bh);
-+ if (err) goto fail;
-+
-+ /* We've shortcircuited the allocation system successfully,
-+ * now finish filling in the inode.
-+ */
-+ goto have_bit_and_group;
-+ }
-+
- repeat:
- gdp = NULL;
- i = 0;
-@@ -470,6 +505,7 @@
- }
- goto repeat;
- }
-+ have_bit_and_group:
- j += i * EXT3_INODES_PER_GROUP(sb) + 1;
- if (j < EXT3_FIRST_INO(sb) || j > le32_to_cpu(es->s_inodes_count)) {
- ext3_error (sb, "ext3_new_inode",
-Index: linux-2.4.24/fs/ext3/inode.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/inode.c 2004-05-19 13:58:43.000000000 +0400
-+++ linux-2.4.24/fs/ext3/inode.c 2004-05-19 13:58:43.000000000 +0400
-@@ -2605,7 +2605,7 @@
- if (IS_ERR(handle))
- goto out_truncate;
-
-- new_inode = ext3_new_inode(handle, old_inode, old_inode->i_mode);
-+ new_inode = ext3_new_inode(handle, old_inode, old_inode->i_mode, 0);
- if (IS_ERR(new_inode)) {
- ext3_debug("truncate inode %lu directly (no new inodes)\n",
- old_inode->i_ino);
-Index: linux-2.4.24/fs/ext3/ioctl.c
-===================================================================
---- linux-2.4.24.orig/fs/ext3/ioctl.c 2004-01-10 17:04:42.000000000 +0300
-+++ linux-2.4.24/fs/ext3/ioctl.c 2004-05-19 13:58:43.000000000 +0400
-@@ -23,6 +23,31 @@
- ext3_debug ("cmd = %u, arg = %lu\n", cmd, arg);
-
- switch (cmd) {
-+ case EXT3_IOC_CREATE_INUM: {
-+ char name[32];
-+ struct dentry *dchild, *dparent;
-+ int rc = 0;
-+
-+ dparent = list_entry(inode->i_dentry.next, struct dentry,
-+ d_alias);
-+ snprintf(name, sizeof name, "%lu", arg);
-+ dchild = lookup_one_len(name, dparent, strlen(name));
-+ if (dchild->d_inode) {
-+ printk(KERN_ERR "%*s/%lu already exists (ino %lu)\n",
-+ dparent->d_name.len, dparent->d_name.name, arg,
-+ dchild->d_inode->i_ino);
-+ rc = -EEXIST;
-+ } else {
-+ dchild->d_fsdata = (void *)arg;
-+ rc = vfs_create(inode, dchild, 0644);
-+ if (rc)
-+ printk(KERN_ERR "vfs_create: %d\n", rc);
-+ else if (dchild->d_inode->i_ino != arg)
-+ rc = -EEXIST;
-+ }
-+ dput(dchild);
-+ return rc;
-+ }
- case EXT3_IOC_GETFLAGS:
- flags = inode->u.ext3_i.i_flags & EXT3_FL_USER_VISIBLE;
- return put_user(flags, (int *) arg);
-Index: linux-2.4.24/include/linux/ext3_fs.h
-===================================================================
---- linux-2.4.24.orig/include/linux/ext3_fs.h 2004-05-19 13:58:43.000000000 +0400
-+++ linux-2.4.24/include/linux/ext3_fs.h 2004-05-19 13:58:43.000000000 +0400
-@@ -202,6 +202,7 @@
- #define EXT3_IOC_SETFLAGS _IOW('f', 2, long)
- #define EXT3_IOC_GETVERSION _IOR('f', 3, long)
- #define EXT3_IOC_SETVERSION _IOW('f', 4, long)
-+/* EXT3_IOC_CREATE_INUM at bottom of file (visible to kernel and user). */
- #define EXT3_IOC_GETVERSION_OLD _IOR('v', 1, long)
- #define EXT3_IOC_SETVERSION_OLD _IOW('v', 2, long)
- #ifdef CONFIG_JBD_DEBUG
-@@ -674,7 +675,8 @@
- dx_hash_info *hinfo);
-
- /* ialloc.c */
--extern struct inode * ext3_new_inode (handle_t *, const struct inode *, int);
-+extern struct inode * ext3_new_inode (handle_t *, const struct inode *, int,
-+ unsigned long);
- extern void ext3_free_inode (handle_t *, struct inode *);
- extern struct inode * ext3_orphan_get (struct super_block *, unsigned long);
- extern unsigned long ext3_count_free_inodes (struct super_block *);
-@@ -766,4 +768,5 @@
-
- #endif /* __KERNEL__ */
-
-+#define EXT3_IOC_CREATE_INUM _IOW('f', 5, long)
- #endif /* _LINUX_EXT3_FS_H */
-Index: linux-2.4.24/include/linux/dcache.h
-===================================================================
---- linux-2.4.24.orig/include/linux/dcache.h 2004-05-19 13:58:42.000000000 +0400
-+++ linux-2.4.24/include/linux/dcache.h 2004-05-21 18:20:34.000000000 +0400
-@@ -63,6 +63,12 @@
-
- #define IS_ROOT(x) ((x) == (x)->d_parent)
-
-+struct dentry_params {
-+ unsigned long p_inum;
-+ unsigned long p_generation;
-+ void *p_ptr;
-+};
-+
- /*
- * "quick string" -- eases parameter passing, but more importantly
- * saves "metadata" about the string (ie length and the hash).
+++ /dev/null
-Index: linux-2.4.21-suse2/include/linux/mm.h
-===================================================================
---- linux-2.4.21-suse2.orig/include/linux/mm.h 2004-01-10 15:51:22.000000000 +0300
-+++ linux-2.4.21-suse2/include/linux/mm.h 2004-01-10 16:02:42.000000000 +0300
-@@ -661,6 +661,7 @@
- #define __GFP_IO 0x40 /* Can start low memory physical IO? */
- #define __GFP_HIGHIO 0x80 /* Can start high mem physical IO? */
- #define __GFP_FS 0x100 /* Can call down to low-level FS? */
-+#define __GFP_MEMALLOC 0x200 /* like PF_MEMALLOC: see __alloc_pages */
-
- #define GFP_NOHIGHIO (__GFP_HIGH | __GFP_WAIT | __GFP_IO)
- #define GFP_NOIO (__GFP_HIGH | __GFP_WAIT)
-@@ -671,6 +672,7 @@
- #define GFP_KERNEL (__GFP_HIGH | __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS)
- #define GFP_NFS (__GFP_HIGH | __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS)
- #define GFP_KSWAPD ( __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS)
-+#define GFP_MEMALLOC __GFP_MEMALLOC
-
- /* Flag - indicates that the buffer will be suitable for DMA. Ignored on some
- platforms, used as appropriate on others */
-Index: linux-2.4.21-suse2/include/linux/slab.h
-===================================================================
---- linux-2.4.21-suse2.orig/include/linux/slab.h 2004-01-10 12:48:36.000000000 +0300
-+++ linux-2.4.21-suse2/include/linux/slab.h 2004-01-10 16:02:42.000000000 +0300
-@@ -23,6 +23,7 @@
- #define SLAB_KERNEL GFP_KERNEL
- #define SLAB_NFS GFP_NFS
- #define SLAB_DMA GFP_DMA
-+#define SLAB_MEMALLOC GFP_MEMALLOC
-
- #define SLAB_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_HIGHIO|__GFP_FS)
- #define SLAB_NO_GROW 0x00001000UL /* don't grow a cache */
-Index: linux-2.4.21-suse2/mm/page_alloc.c
-===================================================================
---- linux-2.4.21-suse2.orig/mm/page_alloc.c 2004-01-10 14:56:13.000000000 +0300
-+++ linux-2.4.21-suse2/mm/page_alloc.c 2004-01-10 16:03:20.000000000 +0300
-@@ -448,7 +448,8 @@
-
- /* here we're in the low on memory slow path */
-
-- if (current->flags & PF_MEMALLOC && !in_interrupt()) {
-+ if (((current->flags & PF_MEMALLOC) || (gfp_mask & __GFP_MEMALLOC))
-+ && !in_interrupt()) {
- zone = zonelist->zones;
- for (;;) {
- zone_t *z = *(zone++);
-Index: linux-2.4.21-suse2/mm/slab.c
-===================================================================
---- linux-2.4.21-suse2.orig/mm/slab.c 2003-10-28 21:33:57.000000000 +0300
-+++ linux-2.4.21-suse2/mm/slab.c 2004-01-10 16:02:42.000000000 +0300
-@@ -1115,7 +1115,7 @@
- /* Be lazy and only check for valid flags here,
- * keeping it out of the critical path in kmem_cache_alloc().
- */
-- if (flags & ~(SLAB_DMA|SLAB_LEVEL_MASK|SLAB_NO_GROW))
-+ if (flags & ~(SLAB_DMA|SLAB_LEVEL_MASK|SLAB_NO_GROW|SLAB_MEMALLOC))
- BUG();
- if (flags & SLAB_NO_GROW)
- return 0;
+++ /dev/null
---- linux-2.4.24-l32/mm/filemap.c.inode_ramax 2004-03-14 13:16:21.000000000 -0800
-+++ linux-2.4.24-l32/mm/filemap.c 2004-03-16 10:57:14.000000000 -0800
-@@ -1226,6 +1226,8 @@
-
- static inline int get_max_readahead(struct inode * inode)
- {
-+ if (inode->i_mapping->a_ops->max_readahead)
-+ return inode->i_mapping->a_ops->max_readahead(inode);
- if (!inode->i_dev || !max_readahead[MAJOR(inode->i_dev)])
- return vm_max_readahead;
- return max_readahead[MAJOR(inode->i_dev)][MINOR(inode->i_dev)];
---- linux-2.4.24-l32/include/linux/fs.h.inode_ramax 2004-03-14 13:15:49.000000000 -0800
-+++ linux-2.4.24-l32/include/linux/fs.h 2004-03-15 11:56:56.000000000 -0800
-@@ -410,6 +410,8 @@
- #define KERNEL_HAS_DIRECT_FILEIO /* Unfortunate kludge due to lack of foresight */
- int (*direct_fileIO)(int, struct file *, struct kiobuf *, unsigned long, int);
- void (*removepage)(struct page *); /* called when page gets removed from the inode */
-+#define KERNEL_HAS_AS_MAX_READAHEAD
-+ int (*max_readahead)(struct inode *);
- };
-
- struct address_space {
+++ /dev/null
-
-
-
- fs/inode.c | 21 ++++++++++++++-------
- fs/smbfs/inode.c | 2 +-
- fs/super.c | 4 ++--
- include/linux/fs.h | 2 +-
- 4 files changed, 18 insertions(+), 11 deletions(-)
-
---- linux-rh-2.4.20-8/fs/inode.c~invalidate_show 2003-04-11 14:04:56.000000000 +0800
-+++ linux-rh-2.4.20-8-root/fs/inode.c 2003-04-16 20:59:35.000000000 +0800
-@@ -604,7 +604,8 @@ static void dispose_list(struct list_hea
- /*
- * Invalidate all inodes for a device.
- */
--static int invalidate_list(struct list_head *head, struct super_block * sb, struct list_head * dispose)
-+static int invalidate_list(struct list_head *head, struct super_block * sb,
-+ struct list_head * dispose, int show)
- {
- struct list_head *next;
- int busy = 0, count = 0;
-@@ -629,6 +630,11 @@ static int invalidate_list(struct list_h
- count++;
- continue;
- }
-+ if (show)
-+ printk(KERN_ERR
-+ "inode busy: dev %s:%lu (%p) mode %o count %u\n",
-+ kdevname(sb->s_dev), inode->i_ino, inode,
-+ inode->i_mode, atomic_read(&inode->i_count));
- busy = 1;
- }
- /* only unused inodes may be cached with i_count zero */
-@@ -647,22 +653,23 @@ static int invalidate_list(struct list_h
- /**
- * invalidate_inodes - discard the inodes on a device
- * @sb: superblock
-+ * @show: whether we should display any busy inodes found
- *
- * Discard all of the inodes for a given superblock. If the discard
- * fails because there are busy inodes then a non zero value is returned.
- * If the discard is successful all the inodes have been discarded.
- */
-
--int invalidate_inodes(struct super_block * sb)
-+int invalidate_inodes(struct super_block * sb, int show)
- {
- int busy;
- LIST_HEAD(throw_away);
-
- spin_lock(&inode_lock);
-- busy = invalidate_list(&inode_in_use, sb, &throw_away);
-- busy |= invalidate_list(&inode_unused, sb, &throw_away);
-- busy |= invalidate_list(&sb->s_dirty, sb, &throw_away);
-- busy |= invalidate_list(&sb->s_locked_inodes, sb, &throw_away);
-+ busy = invalidate_list(&inode_in_use, sb, &throw_away, show);
-+ busy |= invalidate_list(&inode_unused, sb, &throw_away, show);
-+ busy |= invalidate_list(&sb->s_dirty, sb, &throw_away, show);
-+ busy |= invalidate_list(&sb->s_locked_inodes, sb, &throw_away, show);
- spin_unlock(&inode_lock);
-
- dispose_list(&throw_away);
-@@ -688,7 +695,7 @@ int invalidate_device(kdev_t dev, int do
- * hold).
- */
- shrink_dcache_sb(sb);
-- res = invalidate_inodes(sb);
-+ res = invalidate_inodes(sb, 0);
- drop_super(sb);
- }
- invalidate_buffers(dev);
---- linux-rh-2.4.20-8/fs/super.c~invalidate_show 2003-04-11 14:04:57.000000000 +0800
-+++ linux-rh-2.4.20-8-root/fs/super.c 2003-04-16 20:59:35.000000000 +0800
-@@ -943,7 +943,7 @@ void kill_super(struct super_block *sb)
- lock_super(sb);
- lock_kernel();
- sb->s_flags &= ~MS_ACTIVE;
-- invalidate_inodes(sb); /* bad name - it should be evict_inodes() */
-+ invalidate_inodes(sb, 0); /* bad name - it should be evict_inodes() */
- if (sop) {
- if (sop->write_super && sb->s_dirt)
- sop->write_super(sb);
-@@ -952,7 +952,7 @@ void kill_super(struct super_block *sb)
- }
-
- /* Forget any remaining inodes */
-- if (invalidate_inodes(sb)) {
-+ if (invalidate_inodes(sb, 1)) {
- printk(KERN_ERR "VFS: Busy inodes after unmount. "
- "Self-destruct in 5 seconds. Have a nice day...\n");
- }
---- linux-rh-2.4.20-8/include/linux/fs.h~invalidate_show 2003-04-16 20:55:35.000000000 +0800
-+++ linux-rh-2.4.20-8-root/include/linux/fs.h 2003-04-16 20:59:35.000000000 +0800
-@@ -1283,7 +1283,7 @@ static inline void mark_buffer_dirty_ino
- extern void set_buffer_flushtime(struct buffer_head *);
- extern void balance_dirty(void);
- extern int check_disk_change(kdev_t);
--extern int invalidate_inodes(struct super_block *);
-+extern int invalidate_inodes(struct super_block *, int);
- extern int invalidate_device(kdev_t, int);
- extern void invalidate_inode_pages(struct inode *);
- extern void invalidate_inode_pages2(struct address_space *);
---- linux-rh-2.4.20-8/fs/smbfs/inode.c~invalidate_show 2003-04-16 20:59:48.000000000 +0800
-+++ linux-rh-2.4.20-8-root/fs/smbfs/inode.c 2003-04-16 21:00:43.000000000 +0800
-@@ -167,7 +167,7 @@ smb_invalidate_inodes(struct smb_sb_info
- {
- VERBOSE("\n");
- shrink_dcache_sb(SB_of(server));
-- invalidate_inodes(SB_of(server));
-+ invalidate_inodes(SB_of(server), 0);
- }
-
- /*
-
-_
+++ /dev/null
- fs/Makefile | 2 +-
- fs/inode.c | 4 +++-
- mm/page_alloc.c | 1 +
- 3 files changed, 5 insertions(+), 2 deletions(-)
-
---- linux-2.4.20/fs/inode.c~iod-stock-24-exports Wed Apr 2 23:21:20 2003
-+++ linux-2.4.20-braam/fs/inode.c Wed Apr 2 23:21:20 2003
-@@ -5,6 +5,7 @@
- */
-
- #include <linux/config.h>
-+#include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/string.h>
- #include <linux/mm.h>
-@@ -66,7 +67,8 @@ static LIST_HEAD(anon_hash_chain); /* fo
- * NOTE! You also have to own the lock if you change
- * the i_state of an inode while it is in use..
- */
--static spinlock_t inode_lock = SPIN_LOCK_UNLOCKED;
-+spinlock_t inode_lock = SPIN_LOCK_UNLOCKED;
-+EXPORT_SYMBOL(inode_lock);
-
- /*
- * Statistics gathering..
---- linux-2.4.20/fs/Makefile~iod-stock-24-exports Wed Apr 2 23:21:20 2003
-+++ linux-2.4.20-braam/fs/Makefile Wed Apr 2 23:21:53 2003
-@@ -7,7 +7,7 @@
-
- O_TARGET := fs.o
-
--export-objs := filesystems.o open.o dcache.o buffer.o
-+export-objs := filesystems.o open.o dcache.o buffer.o inode.o
- mod-subdirs := nls
-
- obj-y := open.o read_write.o devices.o file_table.o buffer.o \
---- linux-2.4.20/mm/page_alloc.c~iod-stock-24-exports Wed Apr 2 23:21:20 2003
-+++ linux-2.4.20-braam/mm/page_alloc.c Wed Apr 2 23:21:20 2003
-@@ -28,6 +28,7 @@ int nr_inactive_pages;
- LIST_HEAD(inactive_list);
- LIST_HEAD(active_list);
- pg_data_t *pgdat_list;
-+EXPORT_SYMBOL(pgdat_list);
-
- /*
- *
-
-_
+++ /dev/null
- fs/Makefile | 2 +-
- fs/inode.c | 4 +++-
- mm/page_alloc.c | 1 +
- 3 files changed, 5 insertions(+), 2 deletions(-)
-
-Index: linux-2.4.22-vanilla/fs/inode.c
-===================================================================
---- linux-2.4.22-vanilla.orig/fs/inode.c 2003-11-03 23:22:24.000000000 +0300
-+++ linux-2.4.22-vanilla/fs/inode.c 2003-11-03 23:25:00.000000000 +0300
-@@ -5,6 +5,7 @@
- */
-
- #include <linux/config.h>
-+#include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/string.h>
- #include <linux/mm.h>
-@@ -66,7 +67,8 @@
- * NOTE! You also have to own the lock if you change
- * the i_state of an inode while it is in use..
- */
--static spinlock_t inode_lock = SPIN_LOCK_UNLOCKED;
-+spinlock_t inode_lock = SPIN_LOCK_UNLOCKED;
-+EXPORT_SYMBOL(inode_lock);
-
- /*
- * Statistics gathering..
-Index: linux-2.4.22-vanilla/fs/Makefile
-===================================================================
---- linux-2.4.22-vanilla.orig/fs/Makefile 2003-11-03 23:22:11.000000000 +0300
-+++ linux-2.4.22-vanilla/fs/Makefile 2003-11-03 23:25:24.000000000 +0300
-@@ -7,7 +7,7 @@
-
- O_TARGET := fs.o
-
--export-objs := filesystems.o open.o dcache.o buffer.o dquot.o
-+export-objs := filesystems.o open.o dcache.o buffer.o dquot.o inode.o
- mod-subdirs := nls
-
- obj-y := open.o read_write.o devices.o file_table.o buffer.o \
-Index: linux-2.4.22-vanilla/mm/page_alloc.c
-===================================================================
---- linux-2.4.22-vanilla.orig/mm/page_alloc.c 2003-11-03 23:21:29.000000000 +0300
-+++ linux-2.4.22-vanilla/mm/page_alloc.c 2003-11-03 23:25:00.000000000 +0300
-@@ -28,6 +28,7 @@
- LIST_HEAD(inactive_list);
- LIST_HEAD(active_list);
- pg_data_t *pgdat_list;
-+EXPORT_SYMBOL(pgdat_list);
-
- /*
- *
+++ /dev/null
- Documentation/filesystems/ext2.txt | 16 ++
- fs/ext3/Makefile | 2
- fs/ext3/inode.c | 4
- fs/ext3/iopen.c | 259 +++++++++++++++++++++++++++++++++++++
- fs/ext3/iopen.h | 13 +
- fs/ext3/namei.c | 13 +
- fs/ext3/super.c | 11 +
- include/linux/ext3_fs.h | 2
- 8 files changed, 318 insertions(+), 2 deletions(-)
-
-Index: lum/Documentation/filesystems/ext2.txt
-===================================================================
---- lum.orig/Documentation/filesystems/ext2.txt 2001-07-11 16:44:45.000000000 -0600
-+++ lum/Documentation/filesystems/ext2.txt 2004-03-09 16:46:38.000000000 -0700
-@@ -35,6 +35,22 @@
-
- sb=n Use alternate superblock at this location.
-
-+iopen Makes an invisible pseudo-directory called
-+ __iopen__ available in the root directory
-+ of the filesystem. Allows open-by-inode-
-+ number. i.e., inode 3145 can be accessed
-+ via /mntpt/__iopen__/3145
-+
-+iopen_nopriv This option makes the iopen directory be
-+ world-readable. This may be safer since it
-+ allows daemons to run as an unprivileged user,
-+ however it significantly changes the security
-+ model of a Unix filesystem, since previously
-+ all files under a mode 700 directory were not
-+ generally avilable even if the
-+ permissions on the file itself is
-+ world-readable.
-+
- grpquota,noquota,quota,usrquota Quota options are silently ignored by ext2.
-
-
-Index: lum/fs/ext3/Makefile
-===================================================================
---- lum.orig/fs/ext3/Makefile 2004-01-30 14:54:50.000000000 -0700
-+++ lum/fs/ext3/Makefile 2004-03-09 16:46:39.000000000 -0700
-@@ -11,7 +11,7 @@
-
- export-objs := ext3-exports.o
-
--obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
-+obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
- ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o
- obj-m := $(O_TARGET)
-
-Index: lum/fs/ext3/inode.c
-===================================================================
---- lum.orig/fs/ext3/inode.c 2004-01-30 14:54:55.000000000 -0700
-+++ lum/fs/ext3/inode.c 2004-03-09 16:46:41.000000000 -0700
-@@ -31,6 +31,7 @@
- #include <linux/highuid.h>
- #include <linux/quotaops.h>
- #include <linux/module.h>
-+#include "iopen.h"
-
- /*
- * SEARCH_FROM_ZERO forces each block allocation to search from the start
-@@ -2153,6 +2154,9 @@
- struct buffer_head *bh;
- int block;
-
-+ if (ext3_iopen_get_inode(inode))
-+ return;
-+
- if(ext3_get_inode_loc(inode, &iloc))
- goto bad_inode;
- bh = iloc.bh;
-Index: lum/fs/ext3/iopen.c
-===================================================================
---- lum.orig/fs/ext3/iopen.c 2004-03-09 16:46:37.000000000 -0700
-+++ lum/fs/ext3/iopen.c 2004-03-09 16:48:03.000000000 -0700
-@@ -0,0 +1,282 @@
-+/*
-+ * linux/fs/ext3/iopen.c
-+ *
-+ * Special support for open by inode number
-+ *
-+ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
-+ *
-+ * This file may be redistributed under the terms of the GNU General
-+ * Public License.
-+ *
-+ *
-+ * Invariants:
-+ * - there is only ever a single DCACHE_NFSD_DISCONNECTED dentry alias
-+ * for an inode at one time.
-+ * - there are never both connected and DCACHE_NFSD_DISCONNECTED dentry
-+ * aliases on an inode at the same time.
-+ *
-+ * If we have any connected dentry aliases for an inode, use one of those
-+ * in iopen_lookup(). Otherwise, we instantiate a single NFSD_DISCONNECTED
-+ * dentry for this inode, which thereafter will be found by the dcache
-+ * when looking up this inode number in __iopen__, so we don't return here
-+ * until it is gone.
-+ *
-+ * If we get an inode via a regular name lookup, then we "rename" the
-+ * NFSD_DISCONNECTED dentry to the proper name and parent. This ensures
-+ * existing users of the disconnected dentry will continue to use the same
-+ * dentry as the connected users, and there will never be both kinds of
-+ * dentry aliases at one time.
-+ */
-+
-+#include <linux/sched.h>
-+#include <linux/fs.h>
-+#include <linux/locks.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/jbd.h>
-+#include <linux/ext3_fs.h>
-+#include <linux/smp_lock.h>
-+#include "iopen.h"
-+
-+#ifndef assert
-+#define assert(test) J_ASSERT(test)
-+#endif
-+
-+#define IOPEN_NAME_LEN 32
-+
-+/*
-+ * This implements looking up an inode by number.
-+ */
-+static struct dentry *iopen_lookup(struct inode *dir, struct dentry *dentry)
-+{
-+ struct inode *inode;
-+ unsigned long ino;
-+ struct list_head *lp;
-+ struct dentry *alternate;
-+ char buf[IOPEN_NAME_LEN];
-+
-+ if (dentry->d_name.len >= IOPEN_NAME_LEN)
-+ return ERR_PTR(-ENAMETOOLONG);
-+
-+ memcpy(buf, dentry->d_name.name, dentry->d_name.len);
-+ buf[dentry->d_name.len] = 0;
-+
-+ if (strcmp(buf, ".") == 0)
-+ ino = dir->i_ino;
-+ else if (strcmp(buf, "..") == 0)
-+ ino = EXT3_ROOT_INO;
-+ else
-+ ino = simple_strtoul(buf, 0, 0);
-+
-+ if ((ino != EXT3_ROOT_INO &&
-+ //ino != EXT3_ACL_IDX_INO &&
-+ //ino != EXT3_ACL_DATA_INO &&
-+ ino < EXT3_FIRST_INO(dir->i_sb)) ||
-+ ino > le32_to_cpu(dir->i_sb->u.ext3_sb.s_es->s_inodes_count))
-+ return ERR_PTR(-ENOENT);
-+
-+ inode = iget(dir->i_sb, ino);
-+ if (!inode)
-+ return ERR_PTR(-EACCES);
-+ if (is_bad_inode(inode)) {
-+ iput(inode);
-+ return ERR_PTR(-ENOENT);
-+ }
-+
-+ assert(list_empty(&dentry->d_alias)); /* d_instantiate */
-+ assert(list_empty(&dentry->d_hash)); /* d_rehash */
-+
-+ /* preferrably return a connected dentry */
-+ spin_lock(&dcache_lock);
-+ list_for_each(lp, &inode->i_dentry) {
-+ alternate = list_entry(lp, struct dentry, d_alias);
-+ assert(!(alternate->d_flags & DCACHE_NFSD_DISCONNECTED));
-+ }
-+
-+ if (!list_empty(&inode->i_dentry)) {
-+ alternate = list_entry(inode->i_dentry.next,
-+ struct dentry, d_alias);
-+ dget_locked(alternate);
-+ alternate->d_vfs_flags |= DCACHE_REFERENCED;
-+ iput(inode);
-+ spin_unlock(&dcache_lock);
-+ return alternate;
-+ }
-+ dentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
-+
-+ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
-+ list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */
-+ dentry->d_inode = inode;
-+
-+ __d_rehash(dentry, 0); /* d_rehash */
-+ spin_unlock(&dcache_lock);
-+
-+ return NULL;
-+}
-+
-+#define do_switch(x,y) do { \
-+ __typeof__ (x) __tmp = x; \
-+ x = y; y = __tmp; } while (0)
-+
-+static inline void switch_names(struct dentry *dentry, struct dentry *target)
-+{
-+ const unsigned char *old_name, *new_name;
-+
-+ memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN);
-+ old_name = target->d_name.name;
-+ new_name = dentry->d_name.name;
-+ if (old_name == target->d_iname)
-+ old_name = dentry->d_iname;
-+ if (new_name == dentry->d_iname)
-+ new_name = target->d_iname;
-+ target->d_name.name = new_name;
-+ dentry->d_name.name = old_name;
-+}
-+
-+/* This function is spliced into ext3_lookup and does the move of a
-+ * disconnected dentry (if it exists) to a connected dentry.
-+ */
-+struct dentry *iopen_connect_dentry(struct dentry *dentry, struct inode *inode,
-+ int rehash)
-+{
-+ struct dentry *tmp, *goal = NULL;
-+ struct list_head *lp;
-+
-+ /* verify this dentry is really new */
-+ assert(dentry->d_inode == NULL);
-+ assert(list_empty(&dentry->d_alias)); /* d_instantiate */
-+ if (rehash)
-+ assert(list_empty(&dentry->d_hash)); /* d_rehash */
-+ assert(list_empty(&dentry->d_subdirs));
-+
-+ spin_lock(&dcache_lock);
-+ if (!inode)
-+ goto do_rehash;
-+
-+ /* preferrably return a connected dentry */
-+ list_for_each(lp, &inode->i_dentry) {
-+ tmp = list_entry(lp, struct dentry, d_alias);
-+ if (tmp->d_flags & DCACHE_NFSD_DISCONNECTED) {
-+ assert(tmp->d_alias.next == &inode->i_dentry);
-+ assert(tmp->d_alias.prev == &inode->i_dentry);
-+ goal = tmp;
-+ dget_locked(goal);
-+ break;
-+ }
-+ }
-+
-+ if (!goal)
-+ goto do_instantiate;
-+
-+ /* Move the goal to the de hash queue - like d_move() */
-+ goal->d_flags &= ~DCACHE_NFSD_DISCONNECTED;
-+ list_del_init(&goal->d_hash);
-+
-+ list_del(&goal->d_child);
-+ list_del(&dentry->d_child);
-+
-+ /* Switch the parents and the names.. */
-+ switch_names(goal, dentry);
-+ do_switch(goal->d_parent, dentry->d_parent);
-+ do_switch(goal->d_name.len, dentry->d_name.len);
-+ do_switch(goal->d_name.hash, dentry->d_name.hash);
-+
-+ /* And add them back to the (new) parent lists */
-+ list_add(&goal->d_child, &goal->d_parent->d_subdirs);
-+ list_add(&dentry->d_child, &dentry->d_parent->d_subdirs);
-+ __d_rehash(goal, 0);
-+ spin_unlock(&dcache_lock);
-+ iput(inode);
-+
-+ return goal;
-+
-+ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
-+do_instantiate:
-+ list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */
-+ dentry->d_inode = inode;
-+do_rehash:
-+ if (rehash)
-+ __d_rehash(dentry, 0); /* d_rehash */
-+ spin_unlock(&dcache_lock);
-+
-+ return NULL;
-+}
-+
-+/*
-+ * These are the special structures for the iopen pseudo directory.
-+ */
-+
-+static struct inode_operations iopen_inode_operations = {
-+ lookup: iopen_lookup, /* BKL held */
-+};
-+
-+static struct file_operations iopen_file_operations = {
-+ read: generic_read_dir,
-+};
-+
-+static int match_dentry(struct dentry *dentry, const char *name)
-+{
-+ int len;
-+
-+ len = strlen(name);
-+ if (dentry->d_name.len != len)
-+ return 0;
-+ if (strncmp(dentry->d_name.name, name, len))
-+ return 0;
-+ return 1;
-+}
-+
-+/*
-+ * This function is spliced into ext3_lookup and returns 1 the file
-+ * name is __iopen__ and dentry has been filled in appropriately.
-+ */
-+int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry)
-+{
-+ struct inode *inode;
-+
-+ if (dir->i_ino != EXT3_ROOT_INO ||
-+ !test_opt(dir->i_sb, IOPEN) ||
-+ !match_dentry(dentry, "__iopen__"))
-+ return 0;
-+
-+ inode = iget(dir->i_sb, EXT3_BAD_INO);
-+
-+ if (!inode)
-+ return 0;
-+ d_add(dentry, inode);
-+ return 1;
-+}
-+
-+/*
-+ * This function is spliced into read_inode; it returns 1 if inode
-+ * number is the one for /__iopen__, in which case the inode is filled
-+ * in appropriately. Otherwise, this fuction returns 0.
-+ */
-+int ext3_iopen_get_inode(struct inode *inode)
-+{
-+ if (inode->i_ino != EXT3_BAD_INO)
-+ return 0;
-+
-+ inode->i_mode = S_IFDIR | S_IRUSR | S_IXUSR;
-+ if (test_opt(inode->i_sb, IOPEN_NOPRIV))
-+ inode->i_mode |= 0777;
-+ inode->i_uid = 0;
-+ inode->i_gid = 0;
-+ inode->i_nlink = 1;
-+ inode->i_size = 4096;
-+ inode->i_atime = CURRENT_TIME;
-+ inode->i_ctime = CURRENT_TIME;
-+ inode->i_mtime = CURRENT_TIME;
-+ inode->u.ext3_i.i_dtime = 0;
-+ inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size
-+ * (for stat), not the fs block
-+ * size */
-+ inode->i_blocks = 0;
-+ inode->i_version = 1;
-+ inode->i_generation = 0;
-+
-+ inode->i_op = &iopen_inode_operations;
-+ inode->i_fop = &iopen_file_operations;
-+ inode->i_mapping->a_ops = 0;
-+
-+ return 1;
-+}
-Index: lum/fs/ext3/iopen.h
-===================================================================
---- lum.orig/fs/ext3/iopen.h 2004-03-09 16:46:37.000000000 -0700
-+++ lum/fs/ext3/iopen.h 2004-03-09 16:48:03.000000000 -0700
-@@ -0,0 +1,15 @@
-+/*
-+ * iopen.h
-+ *
-+ * Special support for opening files by inode number.
-+ *
-+ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu).
-+ *
-+ * This file may be redistributed under the terms of the GNU General
-+ * Public License.
-+ */
-+
-+extern int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry);
-+extern int ext3_iopen_get_inode(struct inode *inode);
-+extern struct dentry *iopen_connect_dentry(struct dentry *dentry,
-+ struct inode *inode, int rehash);
-Index: lum/fs/ext3/namei.c
-===================================================================
---- lum.orig/fs/ext3/namei.c 2004-01-30 14:54:53.000000000 -0700
-+++ lum/fs/ext3/namei.c 2004-03-09 16:49:25.000000000 -0700
-@@ -35,7 +35,7 @@
- #include <linux/string.h>
- #include <linux/locks.h>
- #include <linux/quotaops.h>
--
-+#include "iopen.h"
-
- /*
- * define how far ahead to read directories while searching them.
-@@ -931,6 +931,9 @@
- if (dentry->d_name.len > EXT3_NAME_LEN)
- return ERR_PTR(-ENAMETOOLONG);
-
-+ if (ext3_check_for_iopen(dir, dentry))
-+ return NULL;
-+
- bh = ext3_find_entry(dentry, &de);
- inode = NULL;
- if (bh) {
-@@ -942,8 +945,8 @@
- return ERR_PTR(-EACCES);
- }
- }
-- d_add(dentry, inode);
-- return NULL;
-+
-+ return iopen_connect_dentry(dentry, inode, 1);
- }
-
- #define S_SHIFT 12
-@@ -1932,10 +1935,6 @@
- inode->i_nlink);
- inode->i_version = ++event;
- inode->i_nlink = 0;
-- /* There's no need to set i_disksize: the fact that i_nlink is
-- * zero will ensure that the right thing happens during any
-- * recovery. */
-- inode->i_size = 0;
- ext3_orphan_add(handle, inode);
- dir->i_nlink--;
- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-@@ -2086,6 +2085,23 @@
- return err;
- }
-
-+/* Like ext3_add_nondir() except for call to iopen_connect_dentry */
-+static int ext3_add_link(handle_t *handle, struct dentry *dentry,
-+ struct inode *inode)
-+{
-+ int err = ext3_add_entry(handle, dentry, inode);
-+ if (!err) {
-+ err = ext3_mark_inode_dirty(handle, inode);
-+ if (err == 0) {
-+ dput(iopen_connect_dentry(dentry, inode, 0));
-+ return 0;
-+ }
-+ }
-+ ext3_dec_count(handle, inode);
-+ iput(inode);
-+ return err;
-+}
-+
- static int ext3_link (struct dentry * old_dentry,
- struct inode * dir, struct dentry *dentry)
- {
-@@ -2113,7 +2129,8 @@
- ext3_inc_count(handle, inode);
- atomic_inc(&inode->i_count);
-
-- err = ext3_add_nondir(handle, dentry, inode);
-+ err = ext3_add_link(handle, dentry, inode);
-+ ext3_orphan_del(handle, inode);
- ext3_journal_stop(handle, dir);
- return err;
- }
-Index: lum/fs/ext3/super.c
-===================================================================
---- lum.orig/fs/ext3/super.c 2004-01-30 14:54:53.000000000 -0700
-+++ lum/fs/ext3/super.c 2004-03-09 16:46:45.000000000 -0700
-@@ -742,6 +742,18 @@
- || !strcmp (this_char, "quota")
- || !strcmp (this_char, "usrquota"))
- /* Don't do anything ;-) */ ;
-+ else if (!strcmp (this_char, "iopen")) {
-+ set_opt (sbi->s_mount_opt, IOPEN);
-+ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
-+ }
-+ else if (!strcmp (this_char, "noiopen")) {
-+ clear_opt (sbi->s_mount_opt, IOPEN);
-+ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
-+ }
-+ else if (!strcmp (this_char, "iopen_nopriv")) {
-+ set_opt (sbi->s_mount_opt, IOPEN);
-+ set_opt (sbi->s_mount_opt, IOPEN_NOPRIV);
-+ }
- else if (!strcmp (this_char, "journal")) {
- /* @@@ FIXME */
- /* Eventually we will want to be able to create
-Index: lum/include/linux/ext3_fs.h
-===================================================================
---- lum.orig/include/linux/ext3_fs.h 2004-01-30 14:54:53.000000000 -0700
-+++ lum/include/linux/ext3_fs.h 2004-03-09 16:46:46.000000000 -0700
-@@ -324,4 +324,6 @@
- #define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
- #define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */
-+#define EXT3_MOUNT_IOPEN 0x40000 /* Allow access via iopen */
-+#define EXT3_MOUNT_IOPEN_NOPRIV 0x80000 /* Make iopen world-readable */
-
- /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
+++ /dev/null
-
---- linux-2.4.18/fs/jbd/checkpoint.c~jbd-commit-tricks Mon Jul 28 13:52:05 2003
-+++ linux-2.4.18-alexey/fs/jbd/checkpoint.c Mon Jul 28 14:03:59 2003
-@@ -77,19 +77,23 @@ static int __try_to_free_cp_buf(struct j
- * to wait for a checkpoint to free up some space in the log.
- */
-
--void log_wait_for_space(journal_t *journal, int nblocks)
-+void log_wait_for_space(journal_t *journal)
- {
-+ int nblocks;
-+
-+ nblocks = jbd_space_needed(journal);
- while (log_space_left(journal) < nblocks) {
- if (journal->j_flags & JFS_ABORT)
- return;
- unlock_journal(journal);
- down(&journal->j_checkpoint_sem);
- lock_journal(journal);
-+ nblocks = jbd_space_needed(journal);
-
- /* Test again, another process may have checkpointed
- * while we were waiting for the checkpoint lock */
- if (log_space_left(journal) < nblocks) {
-- log_do_checkpoint(journal, nblocks);
-+ log_do_checkpoint(journal);
- }
- up(&journal->j_checkpoint_sem);
- }
-@@ -260,8 +264,7 @@ static int __flush_buffer(journal_t *jou
- * The journal should be locked before calling this function.
- */
-
--/* @@@ `nblocks' is unused. Should it be used? */
--int log_do_checkpoint (journal_t *journal, int nblocks)
-+int log_do_checkpoint (journal_t *journal)
- {
- transaction_t *transaction, *last_transaction, *next_transaction;
- int result;
-@@ -315,6 +318,8 @@ repeat:
- retry = __flush_buffer(journal, jh, bhs, &batch_count,
- &drop_count);
- } while (jh != last_jh && !retry);
-+ if (journal->j_checkpoint_transactions != transaction)
-+ goto done;
- if (batch_count) {
- __flush_batch(bhs, &batch_count);
- goto repeat;
-@@ -328,6 +333,8 @@ repeat:
- */
- cleanup_ret = __cleanup_transaction(journal, transaction);
- J_ASSERT(drop_count != 0 || cleanup_ret != 0);
-+ if (journal->j_checkpoint_transactions != transaction)
-+ goto done;
- goto repeat; /* __cleanup may have dropped lock */
- } while (transaction != last_transaction);
-
---- linux-2.4.18/fs/jbd/journal.c~jbd-commit-tricks Mon Jul 28 13:52:05 2003
-+++ linux-2.4.18-alexey/fs/jbd/journal.c Mon Jul 28 14:03:59 2003
-@@ -1115,7 +1115,7 @@ void journal_destroy (journal_t *journal
- /* Force any old transactions to disk */
- lock_journal(journal);
- while (journal->j_checkpoint_transactions != NULL)
-- log_do_checkpoint(journal, 1);
-+ log_do_checkpoint(journal);
-
- J_ASSERT(journal->j_running_transaction == NULL);
- J_ASSERT(journal->j_committing_transaction == NULL);
-@@ -1302,7 +1302,7 @@ int journal_flush (journal_t *journal)
- /* ...and flush everything in the log out to disk. */
- lock_journal(journal);
- while (!err && journal->j_checkpoint_transactions != NULL)
-- err = log_do_checkpoint(journal, journal->j_maxlen);
-+ err = log_do_checkpoint(journal);
- cleanup_journal_tail(journal);
-
- /* Finally, mark the journal as really needing no recovery.
---- linux-2.4.18/fs/jbd/transaction.c~jbd-commit-tricks Mon Jul 28 13:52:05 2003
-+++ linux-2.4.18-alexey/fs/jbd/transaction.c Mon Jul 28 14:03:59 2003
-@@ -182,14 +182,9 @@ repeat_locked:
- * Also, this test is inconsitent with the matching one in
- * journal_extend().
- */
-- needed = journal->j_max_transaction_buffers;
-- if (journal->j_committing_transaction)
-- needed += journal->j_committing_transaction->
-- t_outstanding_credits;
--
-- if (log_space_left(journal) < needed) {
-+ if (log_space_left(journal) < jbd_space_needed(journal)) {
- jbd_debug(2, "Handle %p waiting for checkpoint...\n", handle);
-- log_wait_for_space(journal, needed);
-+ log_wait_for_space(journal);
- goto repeat_locked;
- }
-
---- linux-2.4.18/include/linux/jbd.h~jbd-commit-tricks Mon Jul 28 13:52:17 2003
-+++ linux-2.4.18-alexey/include/linux/jbd.h Mon Jul 28 14:03:59 2003
-@@ -740,9 +740,9 @@ extern void journal_brelse_array(stru
- extern int log_space_left (journal_t *); /* Called with journal locked */
- extern tid_t log_start_commit (journal_t *, transaction_t *);
- extern void log_wait_commit (journal_t *, tid_t);
--extern int log_do_checkpoint (journal_t *, int);
-+extern int log_do_checkpoint (journal_t *);
-
--extern void log_wait_for_space(journal_t *, int nblocks);
-+extern void log_wait_for_space(journal_t *);
- extern void __journal_drop_transaction(journal_t *, transaction_t *);
- extern int cleanup_journal_tail(journal_t *);
-
-@@ -815,6 +815,19 @@ static inline int tid_geq(tid_t x, tid_t
- }
-
- extern int journal_blocks_per_page(struct inode *inode);
-+
-+/*
-+ * Return the minimum number of blocks which must be free in the journal
-+ * before a new transaction may be started. Must be called under j_state_lock.
-+ */
-+static inline int jbd_space_needed(journal_t *journal)
-+{
-+ int nblocks = journal->j_max_transaction_buffers;
-+ if (journal->j_committing_transaction)
-+ nblocks += journal->j_committing_transaction->
-+ t_outstanding_credits;
-+ return nblocks;
-+}
-
- /*
- * Definitions which augment the buffer_head layer
-
-_
+++ /dev/null
-
---- linux-2.4.18/fs/jbd/commit.c~jbd-dont-account-blocks-twice Mon Jul 28 13:52:05 2003
-+++ linux-2.4.18-alexey/fs/jbd/commit.c Mon Jul 28 14:03:53 2003
-@@ -407,6 +407,11 @@ sync_datalist_empty:
- continue;
- }
-
-+ /* start_this_handle() accounts t_outstanding_credits
-+ * to know free space in log, but this counter is changed
-+ * by journal_next_log_block() also. */
-+ commit_transaction->t_outstanding_credits--;
-+
- /* Bump b_count to prevent truncate from stumbling over
- the shadowed buffer! @@@ This can go if we ever get
- rid of the BJ_IO/BJ_Shadow pairing of buffers. */
-
-_
+++ /dev/null
-Index: linux-2.4.22-vanilla/arch/i386/kernel/traps.c
-===================================================================
---- linux-2.4.22-vanilla.orig/arch/i386/kernel/traps.c 2003-05-16 05:28:59.000000000 +0400
-+++ linux-2.4.22-vanilla/arch/i386/kernel/traps.c 2003-11-14 00:35:36.000000000 +0300
-@@ -1004,3 +1004,35 @@
- cobalt_init();
- #endif
- }
-+#ifdef CONFIG_MODULES
-+extern struct module *module_list;
-+extern struct module kernel_module;
-+#endif
-+
-+int is_kernel_text_address(unsigned long addr)
-+{
-+ int retval = 0;
-+#ifdef CONFIG_MODULES
-+ struct module *mod;
-+#endif
-+ if (addr >= (unsigned long) &_stext &&
-+ addr <= (unsigned long) &_etext);
-+ return 1;
-+
-+#ifdef CONFIG_MODULES
-+ for (mod = module_list; mod != &kernel_module; mod = mod->next) {
-+ /* mod_bound tests for addr being inside the vmalloc'ed
-+ * module area. Of course it'd be better to test only
-+ * for the .text subset... */
-+ if (mod_bound(addr, 0, mod)) {
-+ retval = 1;
-+ break;
-+ }
-+ }
-+#endif
-+
-+ return retval;
-+}
-+
-+EXPORT_SYMBOL_GPL(is_kernel_text_address);
-+EXPORT_SYMBOL_GPL(lookup_symbol);
-Index: linux-2.4.22-vanilla/arch/i386/kernel/Makefile
-===================================================================
---- linux-2.4.22-vanilla.orig/arch/i386/kernel/Makefile 2003-11-03 23:22:06.000000000 +0300
-+++ linux-2.4.22-vanilla/arch/i386/kernel/Makefile 2003-11-14 00:30:28.000000000 +0300
-@@ -14,7 +14,8 @@
-
- O_TARGET := kernel.o
-
--export-objs := mca.o mtrr.o msr.o cpuid.o microcode.o i386_ksyms.o time.o setup.o
-+export-objs := mca.o mtrr.o msr.o cpuid.o microcode.o i386_ksyms.o time.o \
-+ setup.o traps.o
-
- obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
- ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
+++ /dev/null
-Index: linux-2.4.24-b1_4/arch/i386/kernel/process.c
-===================================================================
---- linux-2.4.24-b1_4.orig/arch/i386/kernel/process.c 2003-11-29 02:26:19.000000000 +0800
-+++ linux-2.4.24-b1_4/arch/i386/kernel/process.c 2004-09-06 17:53:50.000000000 +0800
-@@ -33,6 +33,7 @@
- #include <linux/reboot.h>
- #include <linux/init.h>
- #include <linux/mc146818rtc.h>
-+#include <linux/version.h>
-
- #include <asm/uaccess.h>
- #include <asm/pgtable.h>
-@@ -447,10 +448,14 @@
- void show_regs(struct pt_regs * regs)
- {
- unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
-+ static char buffer[512];
-+
-+ lookup_symbol(regs->eip,buffer,512);
-
- printk("\n");
- printk("Pid: %d, comm: %20s\n", current->pid, current->comm);
- printk("EIP: %04x:[<%08lx>] CPU: %d",0xffff & regs->xcs,regs->eip, smp_processor_id());
-+ printk("\nEIP is at %s (" UTS_RELEASE ")\n",buffer);
- if (regs->xcs & 3)
- printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp);
- printk(" EFLAGS: %08lx %s\n",regs->eflags, print_tainted());
-Index: linux-2.4.24-b1_4/arch/i386/kernel/traps.c
-===================================================================
---- linux-2.4.24-b1_4.orig/arch/i386/kernel/traps.c 2004-09-06 17:53:35.000000000 +0800
-+++ linux-2.4.24-b1_4/arch/i386/kernel/traps.c 2004-09-06 17:53:50.000000000 +0800
-@@ -24,6 +24,7 @@
- #include <linux/spinlock.h>
- #include <linux/interrupt.h>
- #include <linux/highmem.h>
-+#include <linux/version.h>
-
- #ifdef CONFIG_MCA
- #include <linux/mca.h>
-@@ -135,6 +136,8 @@
- {
- int i;
- unsigned long addr;
-+ /* static to not take up stackspace; if we race here too bad */
-+ static char buffer[512];
-
- if (!stack)
- stack = (unsigned long*)&stack;
-@@ -144,9 +147,8 @@
- while (((long) stack & (THREAD_SIZE-1)) != 0) {
- addr = *stack++;
- if (kernel_text_address(addr)) {
-- if (i && ((i % 6) == 0))
-- printk("\n ");
-- printk(" [<%08lx>]", addr);
-+ lookup_symbol(addr, buffer, 512);
-+ printk("[<%08lx>] %s (0x%x))\n", addr,buffer,stack-1);
- i++;
- }
- }
-@@ -194,12 +196,17 @@
- show_stack(0);
- }
-
-+
-+void print_modules(void);
-+
-+
- void show_registers(struct pt_regs *regs)
- {
- int i;
- int in_kernel = 1;
- unsigned long esp;
- unsigned short ss;
-+ static char buffer[512];
-
- esp = (unsigned long) (®s->esp);
- ss = __KERNEL_DS;
-@@ -208,8 +215,12 @@
- esp = regs->esp;
- ss = regs->xss & 0xffff;
- }
-+
-+ print_modules();
-+ lookup_symbol(regs->eip, buffer, 512);
- printk("CPU: %d\nEIP: %04x:[<%08lx>] %s\nEFLAGS: %08lx\n",
- smp_processor_id(), 0xffff & regs->xcs, regs->eip, print_tainted(), regs->eflags);
-+ printk("\nEIP is at %s (" UTS_RELEASE ")\n",buffer);
- printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
- regs->eax, regs->ebx, regs->ecx, regs->edx);
- printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
-@@ -269,7 +280,7 @@
- if (__get_user(file, (char **)(eip + 4)) ||
- (unsigned long)file < PAGE_OFFSET || __get_user(c, file))
- file = "<bad filename>";
--
-+ printk("------------[ cut here ]------------\n");
- printk("kernel BUG at %s:%d!\n", file, line);
-
- no_bug:
-Index: linux-2.4.24-b1_4/arch/i386/config.in
-===================================================================
---- linux-2.4.24-b1_4.orig/arch/i386/config.in 2004-09-06 17:53:39.000000000 +0800
-+++ linux-2.4.24-b1_4/arch/i386/config.in 2004-09-06 17:53:50.000000000 +0800
-@@ -8,6 +8,7 @@
- define_bool CONFIG_SBUS n
-
- define_bool CONFIG_UID16 y
-+define_bool CONFIG_KALLSYMS y
-
- mainmenu_option next_comment
- comment 'Code maturity level options'
-Index: linux-2.4.24-b1_4/arch/i386/vmlinux.lds.S
-===================================================================
---- linux-2.4.24-b1_4.orig/arch/i386/vmlinux.lds.S 2004-09-06 17:53:39.000000000 +0800
-+++ linux-2.4.24-b1_4/arch/i386/vmlinux.lds.S 2004-09-06 17:53:50.000000000 +0800
-@@ -28,6 +28,11 @@
- __ksymtab : { *(__ksymtab) }
- __stop___ksymtab = .;
-
-+ __start___kallsyms = .; /* All kernel symbols */
-+ __kallsyms : { *(__kallsyms) }
-+ __stop___kallsyms = .;
-+
-+
- .data : { /* Data */
- *(.data)
- CONSTRUCTORS
-Index: linux-2.4.24-b1_4/include/linux/kernel.h
-===================================================================
---- linux-2.4.24-b1_4.orig/include/linux/kernel.h 2004-09-06 17:44:47.000000000 +0800
-+++ linux-2.4.24-b1_4/include/linux/kernel.h 2004-09-06 17:55:19.000000000 +0800
-@@ -110,6 +110,8 @@
-
- extern void dump_stack(void);
-
-+extern int lookup_symbol(unsigned long address, char *buffer, int buflen);
-+
- #if DEBUG
- #define pr_debug(fmt,arg...) \
- printk(KERN_DEBUG fmt,##arg)
-Index: linux-2.4.24-b1_4/include/linux/kallsyms.h
-===================================================================
---- linux-2.4.24-b1_4.orig/include/linux/kallsyms.h 2003-01-30 18:24:37.000000000 +0800
-+++ linux-2.4.24-b1_4/include/linux/kallsyms.h 2004-09-06 17:53:50.000000000 +0800
-@@ -0,0 +1,164 @@
-+/* kallsyms headers
-+ Copyright 2000 Keith Owens <kaos@ocs.com.au>
-+
-+ This file is part of the Linux modutils. It is exported to kernel
-+ space so debuggers can access the kallsyms data.
-+
-+ The kallsyms data contains all the non-stack symbols from a kernel
-+ or a module. The kernel symbols are held between __start___kallsyms
-+ and __stop___kallsyms. The symbols for a module are accessed via
-+ the struct module chain which is based at module_list.
-+
-+ 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.
-+ */
-+
-+#ident "$Id: kksymoops-2.4.24.vanilla.patch,v 1.11 2004/11/11 11:34:26 yury Exp $"
-+
-+#ifndef MODUTILS_KALLSYMS_H
-+#define MODUTILS_KALLSYMS_H 1
-+
-+/* Have to (re)define these ElfW entries here because external kallsyms
-+ * code does not have access to modutils/include/obj.h. This code is
-+ * included from user spaces tools (modutils) and kernel, they need
-+ * different includes.
-+ */
-+
-+#ifndef ELFCLASS32
-+#ifdef __KERNEL__
-+#include <linux/elf.h>
-+#else /* __KERNEL__ */
-+#include <elf.h>
-+#endif /* __KERNEL__ */
-+#endif /* ELFCLASS32 */
-+
-+#ifndef ELFCLASSM
-+#define ELFCLASSM ELF_CLASS
-+#endif
-+
-+#ifndef ElfW
-+# if ELFCLASSM == ELFCLASS32
-+# define ElfW(x) Elf32_ ## x
-+# define ELFW(x) ELF32_ ## x
-+# else
-+# define ElfW(x) Elf64_ ## x
-+# define ELFW(x) ELF64_ ## x
-+# endif
-+#endif
-+
-+/* Format of data in the kallsyms section.
-+ * Most of the fields are small numbers but the total size and all
-+ * offsets can be large so use the 32/64 bit types for these fields.
-+ *
-+ * Do not use sizeof() on these structures, modutils may be using extra
-+ * fields. Instead use the size fields in the header to access the
-+ * other bits of data.
-+ */
-+
-+struct kallsyms_header {
-+ int size; /* Size of this header */
-+ ElfW(Word) total_size; /* Total size of kallsyms data */
-+ int sections; /* Number of section entries */
-+ ElfW(Off) section_off; /* Offset to first section entry */
-+ int section_size; /* Size of one section entry */
-+ int symbols; /* Number of symbol entries */
-+ ElfW(Off) symbol_off; /* Offset to first symbol entry */
-+ int symbol_size; /* Size of one symbol entry */
-+ ElfW(Off) string_off; /* Offset to first string */
-+ ElfW(Addr) start; /* Start address of first section */
-+ ElfW(Addr) end; /* End address of last section */
-+};
-+
-+struct kallsyms_section {
-+ ElfW(Addr) start; /* Start address of section */
-+ ElfW(Word) size; /* Size of this section */
-+ ElfW(Off) name_off; /* Offset to section name */
-+ ElfW(Word) flags; /* Flags from section */
-+};
-+
-+struct kallsyms_symbol {
-+ ElfW(Off) section_off; /* Offset to section that owns this symbol */
-+ ElfW(Addr) symbol_addr; /* Address of symbol */
-+ ElfW(Off) name_off; /* Offset to symbol name */
-+};
-+
-+#define KALLSYMS_SEC_NAME "__kallsyms"
-+#define KALLSYMS_IDX 2 /* obj_kallsyms creates kallsyms as section 2 */
-+
-+#define kallsyms_next_sec(h,s) \
-+ ((s) = (struct kallsyms_section *)((char *)(s) + (h)->section_size))
-+#define kallsyms_next_sym(h,s) \
-+ ((s) = (struct kallsyms_symbol *)((char *)(s) + (h)->symbol_size))
-+
-+#ifdef CONFIG_KALLSYMS
-+
-+int kallsyms_symbol_to_address(
-+ const char *name, /* Name to lookup */
-+ unsigned long *token, /* Which module to start with */
-+ const char **mod_name, /* Set to module name or "kernel" */
-+ unsigned long *mod_start, /* Set to start address of module */
-+ unsigned long *mod_end, /* Set to end address of module */
-+ const char **sec_name, /* Set to section name */
-+ unsigned long *sec_start, /* Set to start address of section */
-+ unsigned long *sec_end, /* Set to end address of section */
-+ const char **sym_name, /* Set to full symbol name */
-+ unsigned long *sym_start, /* Set to start address of symbol */
-+ unsigned long *sym_end /* Set to end address of symbol */
-+ );
-+
-+int kallsyms_address_to_symbol(
-+ unsigned long address, /* Address to lookup */
-+ const char **mod_name, /* Set to module name */
-+ unsigned long *mod_start, /* Set to start address of module */
-+ unsigned long *mod_end, /* Set to end address of module */
-+ const char **sec_name, /* Set to section name */
-+ unsigned long *sec_start, /* Set to start address of section */
-+ unsigned long *sec_end, /* Set to end address of section */
-+ const char **sym_name, /* Set to full symbol name */
-+ unsigned long *sym_start, /* Set to start address of symbol */
-+ unsigned long *sym_end /* Set to end address of symbol */
-+ );
-+
-+int kallsyms_sections(void *token,
-+ int (*callback)(void *, /* token */
-+ const char *, /* module name */
-+ const char *, /* section name */
-+ ElfW(Addr), /* Section start */
-+ ElfW(Addr), /* Section end */
-+ ElfW(Word) /* Section flags */
-+ )
-+ );
-+
-+#else
-+
-+static inline int kallsyms_address_to_symbol(
-+ unsigned long address, /* Address to lookup */
-+ const char **mod_name, /* Set to module name */
-+ unsigned long *mod_start, /* Set to start address of module */
-+ unsigned long *mod_end, /* Set to end address of module */
-+ const char **sec_name, /* Set to section name */
-+ unsigned long *sec_start, /* Set to start address of section */
-+ unsigned long *sec_end, /* Set to end address of section */
-+ const char **sym_name, /* Set to full symbol name */
-+ unsigned long *sym_start, /* Set to start address of symbol */
-+ unsigned long *sym_end /* Set to end address of symbol */
-+ )
-+{
-+ return -ESRCH;
-+}
-+
-+#endif
-+
-+#endif /* kallsyms.h */
-+
-Index: linux-2.4.24-b1_4/kernel/kksymoops.c
-===================================================================
---- linux-2.4.24-b1_4.orig/kernel/kksymoops.c 2003-01-30 18:24:37.000000000 +0800
-+++ linux-2.4.24-b1_4/kernel/kksymoops.c 2004-09-06 17:53:50.000000000 +0800
-@@ -0,0 +1,82 @@
-+#include <linux/module.h>
-+#include <linux/string.h>
-+#include <linux/errno.h>
-+#include <linux/kernel.h>
-+#include <linux/config.h>
-+#ifdef CONFIG_KALLSYMS
-+#include <linux/kallsyms.h>
-+#endif
-+
-+
-+
-+int lookup_symbol(unsigned long address, char *buffer, int buflen)
-+{
-+ struct module *this_mod;
-+ unsigned long bestsofar;
-+
-+ const char *mod_name = NULL, *sec_name = NULL, *sym_name = NULL;
-+ unsigned long mod_start,mod_end,sec_start,sec_end,sym_start,sym_end;
-+
-+ if (!buffer)
-+ return -EFAULT;
-+
-+ if (buflen<256)
-+ return -ENOMEM;
-+
-+ memset(buffer,0,buflen);
-+
-+#ifdef CONFIG_KALLSYMS
-+ if (!kallsyms_address_to_symbol(address,&mod_name,&mod_start,&mod_end,&sec_name,
-+ &sec_start, &sec_end, &sym_name, &sym_start, &sym_end)) {
-+ /* kallsyms doesn't have a clue; lets try harder */
-+ bestsofar = 0;
-+ snprintf(buffer,buflen-1,"[unresolved]");
-+
-+ this_mod = module_list;
-+
-+ while (this_mod != NULL) {
-+ int i;
-+ /* walk the symbol list of this module. Only symbols
-+ who's address is smaller than the searched for address
-+ are relevant; and only if it's better than the best so far */
-+ for (i=0; i< this_mod->nsyms; i++)
-+ if ((this_mod->syms[i].value<=address) &&
-+ (bestsofar<this_mod->syms[i].value)) {
-+ snprintf(buffer,buflen-1,"%s [%s] 0x%x",
-+ this_mod->syms[i].name,
-+ this_mod->name,
-+ (unsigned int)(address - this_mod->syms[i].value));
-+ bestsofar = this_mod->syms[i].value;
-+ }
-+ this_mod = this_mod->next;
-+ }
-+
-+ } else { /* kallsyms success */
-+ snprintf(buffer,buflen-1,"%s [%s] 0x%x",sym_name,mod_name,(unsigned int)(address-sym_start));
-+ }
-+#endif
-+ return strlen(buffer);
-+}
-+
-+static char modlist[4096];
-+/* this function isn't smp safe but that's not really a problem; it's called from
-+ * oops context only and any locking could actually prevent the oops from going out;
-+ * the line that is generated is informational only and should NEVER prevent the real oops
-+ * from going out.
-+ */
-+void print_modules(void)
-+{
-+ struct module *this_mod;
-+ int pos = 0;
-+ memset(modlist,0,4096);
-+
-+#ifdef CONFIG_KALLSYMS
-+ this_mod = module_list;
-+ while (this_mod != NULL) {
-+ if (this_mod->name != NULL)
-+ pos +=snprintf(modlist+pos,160-pos-1,"%s ",this_mod->name);
-+ this_mod = this_mod->next;
-+ }
-+ printk("%s\n",modlist);
-+#endif
-+}
-Index: linux-2.4.24-b1_4/kernel/Makefile
-===================================================================
---- linux-2.4.24-b1_4.orig/kernel/Makefile 2001-09-17 12:22:40.000000000 +0800
-+++ linux-2.4.24-b1_4/kernel/Makefile 2004-09-06 17:56:17.000000000 +0800
-@@ -29,4 +29,7 @@
- CFLAGS_sched.o := $(PROFILING) -fno-omit-frame-pointer
- endif
-
-+obj-$(CONFIG_KALLSYMS) += kksymoops.o
-+obj-$(CONFIG_KALLSYMS) += kallsyms.o
-+
- include $(TOPDIR)/Rules.make
-Index: linux-2.4.24-b1_4/kernel/kallsyms.c
-===================================================================
---- linux-2.4.24-b1_4.orig/kernel/kallsyms.c 2003-01-30 18:24:37.000000000 +0800
-+++ linux-2.4.24-b1_4/kernel/kallsyms.c 2004-09-06 17:53:50.000000000 +0800
-@@ -0,0 +1,227 @@
-+/*
-+ * kksymoops.c: in-kernel printing of symbolic oopses and stack traces.
-+ *
-+ * Copyright 2000 Keith Owens <kaos@ocs.com.au> April 2000
-+ * Copyright 2002 Arjan van de Ven <arjanv@redhat.com>
-+ *
-+ This code uses the list of all kernel and module symbols to :-
-+
-+ * Find any non-stack symbol in a kernel or module. Symbols do
-+ not have to be exported for debugging.
-+
-+ * Convert an address to the module (or kernel) that owns it, the
-+ section it is in and the nearest symbol. This finds all non-stack
-+ symbols, not just exported ones.
-+
-+ */
-+
-+#include <linux/mm.h>
-+#include <linux/module.h>
-+#include <linux/kallsyms.h>
-+
-+/* A symbol can appear in more than one module. A token is used to
-+ * restart the scan at the next module, set the token to 0 for the
-+ * first scan of each symbol.
-+ */
-+
-+int kallsyms_symbol_to_address(
-+ const char *name, /* Name to lookup */
-+ unsigned long *token, /* Which module to start at */
-+ const char **mod_name, /* Set to module name */
-+ unsigned long *mod_start, /* Set to start address of module */
-+ unsigned long *mod_end, /* Set to end address of module */
-+ const char **sec_name, /* Set to section name */
-+ unsigned long *sec_start, /* Set to start address of section */
-+ unsigned long *sec_end, /* Set to end address of section */
-+ const char **sym_name, /* Set to full symbol name */
-+ unsigned long *sym_start, /* Set to start address of symbol */
-+ unsigned long *sym_end /* Set to end address of symbol */
-+ )
-+{
-+ const struct kallsyms_header *ka_hdr = NULL; /* stupid gcc */
-+ const struct kallsyms_section *ka_sec;
-+ const struct kallsyms_symbol *ka_sym = NULL;
-+ const char *ka_str = NULL;
-+ const struct module *m;
-+ int i = 0, l;
-+ const char *p, *pt_R;
-+ char *p2;
-+
-+ /* Restart? */
-+ m = module_list;
-+ if (token && *token) {
-+ for (; m; m = m->next)
-+ if ((unsigned long)m == *token)
-+ break;
-+ if (m)
-+ m = m->next;
-+ }
-+
-+ for (; m; m = m->next) {
-+ if (!mod_member_present(m, kallsyms_start) ||
-+ !mod_member_present(m, kallsyms_end) ||
-+ m->kallsyms_start >= m->kallsyms_end)
-+ continue;
-+ ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
-+ ka_sym = (struct kallsyms_symbol *)
-+ ((char *)(ka_hdr) + ka_hdr->symbol_off);
-+ ka_str =
-+ ((char *)(ka_hdr) + ka_hdr->string_off);
-+ for (i = 0; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) {
-+ p = ka_str + ka_sym->name_off;
-+ if (strcmp(p, name) == 0)
-+ break;
-+ /* Unversioned requests match versioned names */
-+ if (!(pt_R = strstr(p, "_R")))
-+ continue;
-+ l = strlen(pt_R);
-+ if (l < 10)
-+ continue; /* Not _R.*xxxxxxxx */
-+ (void)simple_strtoul(pt_R+l-8, &p2, 16);
-+ if (*p2)
-+ continue; /* Not _R.*xxxxxxxx */
-+ if (strncmp(p, name, pt_R-p) == 0)
-+ break; /* Match with version */
-+ }
-+ if (i < ka_hdr->symbols)
-+ break;
-+ }
-+
-+ if (token)
-+ *token = (unsigned long)m;
-+ if (!m)
-+ return(0); /* not found */
-+
-+ ka_sec = (const struct kallsyms_section *)
-+ ((char *)ka_hdr + ka_hdr->section_off + ka_sym->section_off);
-+ *mod_name = m->name;
-+ *mod_start = ka_hdr->start;
-+ *mod_end = ka_hdr->end;
-+ *sec_name = ka_sec->name_off + ka_str;
-+ *sec_start = ka_sec->start;
-+ *sec_end = ka_sec->start + ka_sec->size;
-+ *sym_name = ka_sym->name_off + ka_str;
-+ *sym_start = ka_sym->symbol_addr;
-+ if (i < ka_hdr->symbols-1) {
-+ const struct kallsyms_symbol *ka_symn = ka_sym;
-+ kallsyms_next_sym(ka_hdr, ka_symn);
-+ *sym_end = ka_symn->symbol_addr;
-+ }
-+ else
-+ *sym_end = *sec_end;
-+ return(1);
-+}
-+
-+int kallsyms_address_to_symbol(
-+ unsigned long address, /* Address to lookup */
-+ const char **mod_name, /* Set to module name */
-+ unsigned long *mod_start, /* Set to start address of module */
-+ unsigned long *mod_end, /* Set to end address of module */
-+ const char **sec_name, /* Set to section name */
-+ unsigned long *sec_start, /* Set to start address of section */
-+ unsigned long *sec_end, /* Set to end address of section */
-+ const char **sym_name, /* Set to full symbol name */
-+ unsigned long *sym_start, /* Set to start address of symbol */
-+ unsigned long *sym_end /* Set to end address of symbol */
-+ )
-+{
-+ const struct kallsyms_header *ka_hdr = NULL; /* stupid gcc */
-+ const struct kallsyms_section *ka_sec = NULL;
-+ const struct kallsyms_symbol *ka_sym;
-+ const char *ka_str;
-+ const struct module *m;
-+ int i;
-+ unsigned long end;
-+
-+ for (m = module_list; m; m = m->next) {
-+
-+ if (!mod_member_present(m, kallsyms_start) ||
-+ !mod_member_present(m, kallsyms_end) ||
-+ m->kallsyms_start >= m->kallsyms_end)
-+ continue;
-+ ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
-+ ka_sec = (const struct kallsyms_section *)
-+ ((char *)ka_hdr + ka_hdr->section_off);
-+ /* Is the address in any section in this module? */
-+ for (i = 0; i < ka_hdr->sections; ++i, kallsyms_next_sec(ka_hdr, ka_sec)) {
-+ if (ka_sec->start <= address &&
-+ (ka_sec->start + ka_sec->size) > address)
-+ break;
-+ }
-+ if (i < ka_hdr->sections)
-+ break; /* Found a matching section */
-+ }
-+
-+ if (!m)
-+ return(0); /* not found */
-+
-+ ka_sym = (struct kallsyms_symbol *)
-+ ((char *)(ka_hdr) + ka_hdr->symbol_off);
-+ ka_str =
-+ ((char *)(ka_hdr) + ka_hdr->string_off);
-+ *mod_name = m->name;
-+ *mod_start = ka_hdr->start;
-+ *mod_end = ka_hdr->end;
-+ *sec_name = ka_sec->name_off + ka_str;
-+ *sec_start = ka_sec->start;
-+ *sec_end = ka_sec->start + ka_sec->size;
-+ *sym_name = *sec_name; /* In case we find no matching symbol */
-+ *sym_start = *sec_start;
-+ *sym_end = *sec_end;
-+
-+ for (i = 0; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) {
-+ if (ka_sym->symbol_addr > address)
-+ continue;
-+ if (i < ka_hdr->symbols-1) {
-+ const struct kallsyms_symbol *ka_symn = ka_sym;
-+ kallsyms_next_sym(ka_hdr, ka_symn);
-+ end = ka_symn->symbol_addr;
-+ }
-+ else
-+ end = *sec_end;
-+ if (end <= address)
-+ continue;
-+ if ((char *)ka_hdr + ka_hdr->section_off + ka_sym->section_off
-+ != (char *)ka_sec)
-+ continue; /* wrong section */
-+ *sym_name = ka_str + ka_sym->name_off;
-+ *sym_start = ka_sym->symbol_addr;
-+ *sym_end = end;
-+ break;
-+ }
-+ return(1);
-+}
-+
-+/* List all sections in all modules. The callback routine is invoked with
-+ * token, module name, section name, section start, section end, section flags.
-+ */
-+int kallsyms_sections(void *token,
-+ int (*callback)(void *, const char *, const char *, ElfW(Addr), ElfW(Addr), ElfW(Word)))
-+{
-+ const struct kallsyms_header *ka_hdr = NULL; /* stupid gcc */
-+ const struct kallsyms_section *ka_sec = NULL;
-+ const char *ka_str;
-+ const struct module *m;
-+ int i;
-+
-+ for (m = module_list; m; m = m->next) {
-+ if (!mod_member_present(m, kallsyms_start) ||
-+ !mod_member_present(m, kallsyms_end) ||
-+ m->kallsyms_start >= m->kallsyms_end)
-+ continue;
-+ ka_hdr = (struct kallsyms_header *)m->kallsyms_start;
-+ ka_sec = (const struct kallsyms_section *) ((char *)ka_hdr + ka_hdr->section_off);
-+ ka_str = ((char *)(ka_hdr) + ka_hdr->string_off);
-+ for (i = 0; i < ka_hdr->sections; ++i, kallsyms_next_sec(ka_hdr, ka_sec)) {
-+ if (callback(
-+ token,
-+ *(m->name) ? m->name : "kernel",
-+ ka_sec->name_off + ka_str,
-+ ka_sec->start,
-+ ka_sec->start + ka_sec->size,
-+ ka_sec->flags))
-+ return(0);
-+ }
-+ }
-+ return(1);
-+}
-Index: linux-2.4.24-b1_4/Makefile
-===================================================================
---- linux-2.4.24-b1_4.orig/Makefile 2004-09-06 17:44:47.000000000 +0800
-+++ linux-2.4.24-b1_4/Makefile 2004-09-06 17:53:50.000000000 +0800
-@@ -45,6 +45,7 @@
- MAKEFILES = $(TOPDIR)/.config
- GENKSYMS = /sbin/genksyms
- DEPMOD = /sbin/depmod
-+KALLSYMS = /sbin/kallsyms
- MODFLAGS = -DMODULE
- CFLAGS_KERNEL =
- PERL = perl
-@@ -211,7 +212,7 @@
- CLEAN_FILES = \
- kernel/ksyms.lst include/linux/compile.h \
- vmlinux System.map \
-- .tmp* \
-+ $(TMPPREFIX).tmp* \
- drivers/char/consolemap_deftbl.c drivers/video/promcon_tbl.c \
- drivers/char/conmakehash \
- drivers/char/drm/*-mod.c \
-@@ -292,16 +293,42 @@
- boot: vmlinux
- @$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" -C arch/$(ARCH)/boot
-
-+LD_VMLINUX := $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o init/do_mounts.o \
-+ --start-group \
-+ $(CORE_FILES) \
-+ $(DRIVERS) \
-+ $(NETWORKS) \
-+ $(LIBS) \
-+ --end-group
-+ifeq ($(CONFIG_KALLSYMS),y)
-+LD_VMLINUX_KALLSYMS := $(TMPPREFIX).tmp_kallsyms3.o
-+else
-+LD_VMLINUX_KALLSYMS :=
-+endif
-+
- vmlinux: include/linux/version.h $(CONFIGURATION) init/main.o init/version.o init/do_mounts.o linuxsubdirs
-- $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o init/do_mounts.o \
-- --start-group \
-- $(CORE_FILES) \
-- $(DRIVERS) \
-- $(NETWORKS) \
-- $(LIBS) \
-- --end-group \
-- -o vmlinux
-+ @$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" kallsyms
-+
-+.PHONY: kallsyms
-+
-+kallsyms:
-+ifeq ($(CONFIG_KALLSYMS),y)
-+ @echo kallsyms pass 1
-+ $(LD_VMLINUX) -o $(TMPPREFIX).tmp_vmlinux1
-+ @$(KALLSYMS) $(TMPPREFIX).tmp_vmlinux1 > $(TMPPREFIX).tmp_kallsyms1.o
-+ @echo kallsyms pass 2
-+ @$(LD_VMLINUX) $(TMPPREFIX).tmp_kallsyms1.o -o $(TMPPREFIX).tmp_vmlinux2
-+ @$(KALLSYMS) $(TMPPREFIX).tmp_vmlinux2 > $(TMPPREFIX).tmp_kallsyms2.o
-+ @echo kallsyms pass 3
-+ @$(LD_VMLINUX) $(TMPPREFIX).tmp_kallsyms2.o -o $(TMPPREFIX).tmp_vmlinux3
-+ @$(KALLSYMS) $(TMPPREFIX).tmp_vmlinux3 > $(TMPPREFIX).tmp_kallsyms3.o
-+endif
-+ $(LD_VMLINUX) $(LD_VMLINUX_KALLSYMS) -o $(TMPPREFIX)vmlinux
-+ifneq ($(TMPPREFIX),)
-+ mv $(TMPPREFIX)vmlinux vmlinux
-+endif
- $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
-+ @rm -f $(TMPPREFIX).tmp_vmlinux* $(TMPPREFIX).tmp_kallsyms*
-
- symlinks:
- rm -f include/asm
+++ /dev/null
- Documentation/Configure.help | 66 ++
- arch/alpha/defconfig | 7
- arch/alpha/kernel/entry.S | 12
- arch/arm/defconfig | 7
- arch/arm/kernel/calls.S | 24
- arch/i386/defconfig | 7
- arch/ia64/defconfig | 7
- arch/ia64/kernel/entry.S | 24
- arch/m68k/defconfig | 7
- arch/mips/defconfig | 7
- arch/mips64/defconfig | 7
- arch/ppc/defconfig | 14
- arch/ppc64/kernel/misc.S | 2
- arch/s390/defconfig | 7
- arch/s390/kernel/entry.S | 24
- arch/s390x/defconfig | 7
- arch/s390x/kernel/entry.S | 24
- arch/s390x/kernel/wrapper32.S | 92 +++
- arch/sparc/defconfig | 7
- arch/sparc/kernel/systbls.S | 10
- arch/sparc64/defconfig | 7
- arch/sparc64/kernel/systbls.S | 20
- fs/Config.in | 14
- fs/Makefile | 3
- fs/ext2/Makefile | 4
- fs/ext2/file.c | 5
- fs/ext2/ialloc.c | 2
- fs/ext2/inode.c | 34 -
- fs/ext2/namei.c | 14
- fs/ext2/super.c | 29
- fs/ext2/symlink.c | 14
- fs/ext2/xattr.c | 1212 +++++++++++++++++++++++++++++++++++++++++
- fs/ext2/xattr_user.c | 103 +++
- fs/ext3/Makefile | 10
- fs/ext3/file.c | 5
- fs/ext3/ialloc.c | 2
- fs/ext3/inode.c | 35 -
- fs/ext3/namei.c | 21
- fs/ext3/super.c | 36 +
- fs/ext3/symlink.c | 14
- fs/ext3/xattr.c | 1225 ++++++++++++++++++++++++++++++++++++++++++
- fs/ext3/xattr_user.c | 111 +++
- fs/jfs/jfs_xattr.h | 6
- fs/jfs/xattr.c | 6
- fs/mbcache.c | 648 ++++++++++++++++++++++
- include/asm-arm/unistd.h | 2
- include/asm-ia64/unistd.h | 13
- include/asm-ppc64/unistd.h | 2
- include/asm-s390/unistd.h | 15
- include/asm-s390x/unistd.h | 15
- include/asm-sparc/unistd.h | 24
- include/asm-sparc64/unistd.h | 24
- include/linux/cache_def.h | 15
- include/linux/errno.h | 4
- include/linux/ext2_fs.h | 31 -
- include/linux/ext2_xattr.h | 157 +++++
- include/linux/ext3_fs.h | 31 -
- include/linux/ext3_jbd.h | 8
- include/linux/ext3_xattr.h | 157 +++++
- include/linux/fs.h | 2
- include/linux/mbcache.h | 69 ++
- kernel/ksyms.c | 4
- mm/vmscan.c | 35 +
- fs/ext3/ext3-exports.c | 14 +
- 64 files changed, 4355 insertions(+), 195 deletions(-)
-
-Index: linux-2.4.24-vanilla/Documentation/Configure.help
-===================================================================
---- linux-2.4.24-vanilla.orig/Documentation/Configure.help 2004-01-10 17:05:37.000000000 +0300
-+++ linux-2.4.24-vanilla/Documentation/Configure.help 2004-01-10 17:20:28.000000000 +0300
-@@ -16295,6 +16295,39 @@
- be compiled as a module, and so this could be dangerous. Most
- everyone wants to say Y here.
-
-+Ext2 extended attributes
-+CONFIG_EXT2_FS_XATTR
-+ Extended attributes are name:value pairs associated with inodes by
-+ the kernel or by users (see the attr(5) manual page, or visit
-+ <http://acl.bestbits.at/> for details).
-+
-+ If unsure, say N.
-+
-+Ext2 extended attribute block sharing
-+CONFIG_EXT2_FS_XATTR_SHARING
-+ This options enables code for sharing identical extended attribute
-+ blocks among multiple inodes.
-+
-+ Usually, say Y.
-+
-+Ext2 extended user attributes
-+CONFIG_EXT2_FS_XATTR_USER
-+ This option enables extended user attributes on ext2. Processes can
-+ associate extended user attributes with inodes to store additional
-+ information such as the character encoding of files, etc. (see the
-+ attr(5) manual page, or visit <http://acl.bestbits.at/> for details).
-+
-+ If unsure, say N.
-+
-+Ext2 trusted extended attributes
-+CONFIG_EXT2_FS_XATTR_TRUSTED
-+ This option enables extended attributes on ext2 that are accessible
-+ (and visible) only to users capable of CAP_SYS_ADMIN. Usually this
-+ is only the super user. Trusted extended attributes are meant for
-+ implementing system/security services.
-+
-+ If unsure, say N.
-+
- Ext3 journalling file system support (EXPERIMENTAL)
- CONFIG_EXT3_FS
- This is the journalling version of the Second extended file system
-@@ -16327,6 +16360,39 @@
- of your root partition (the one containing the directory /) cannot
- be compiled as a module, and so this may be dangerous.
-
-+Ext3 extended attributes
-+CONFIG_EXT3_FS_XATTR
-+ Extended attributes are name:value pairs associated with inodes by
-+ the kernel or by users (see the attr(5) manual page, or visit
-+ <http://acl.bestbits.at/> for details).
-+
-+ If unsure, say N.
-+
-+Ext3 extended attribute block sharing
-+CONFIG_EXT3_FS_XATTR_SHARING
-+ This options enables code for sharing identical extended attribute
-+ blocks among multiple inodes.
-+
-+ Usually, say Y.
-+
-+Ext3 extended user attributes
-+CONFIG_EXT3_FS_XATTR_USER
-+ This option enables extended user attributes on ext3. Processes can
-+ associate extended user attributes with inodes to store additional
-+ information such as the character encoding of files, etc. (see the
-+ attr(5) manual page, or visit <http://acl.bestbits.at/> for details).
-+
-+ If unsure, say N.
-+
-+Ext3 trusted extended attributes
-+CONFIG_EXT3_FS_XATTR_TRUSTED
-+ This option enables extended attributes on ext3 that are accessible
-+ (and visible) only to users capable of CAP_SYS_ADMIN. Usually this
-+ is only the super user. Trusted extended attributes are meant for
-+ implementing system/security services.
-+
-+ If unsure, say N.
-+
- Journal Block Device support (JBD for ext3) (EXPERIMENTAL)
- CONFIG_JBD
- This is a generic journalling layer for block devices. It is
-Index: linux-2.4.24-vanilla/arch/alpha/defconfig
-===================================================================
---- linux-2.4.24-vanilla.orig/arch/alpha/defconfig 2004-01-10 17:04:37.000000000 +0300
-+++ linux-2.4.24-vanilla/arch/alpha/defconfig 2004-01-10 17:20:28.000000000 +0300
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_ALPHA=y
- # CONFIG_UID16 is not set
- # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
-Index: linux-2.4.24-vanilla/arch/alpha/kernel/entry.S
-===================================================================
---- linux-2.4.24-vanilla.orig/arch/alpha/kernel/entry.S 2004-01-10 17:04:37.000000000 +0300
-+++ linux-2.4.24-vanilla/arch/alpha/kernel/entry.S 2004-01-10 17:20:28.000000000 +0300
-@@ -1154,6 +1154,18 @@
- .quad sys_readahead
- .quad sys_ni_syscall /* 380, sys_security */
- .quad sys_tkill
-+ .quad sys_setxattr
-+ .quad sys_lsetxattr
-+ .quad sys_fsetxattr
-+ .quad sys_getxattr /* 385 */
-+ .quad sys_lgetxattr
-+ .quad sys_fgetxattr
-+ .quad sys_listxattr
-+ .quad sys_llistxattr
-+ .quad sys_flistxattr /* 390 */
-+ .quad sys_removexattr
-+ .quad sys_lremovexattr
-+ .quad sys_fremovexattr
-
- /* Remember to update everything, kids. */
- .ifne (. - sys_call_table) - (NR_SYSCALLS * 8)
-Index: linux-2.4.24-vanilla/arch/arm/defconfig
-===================================================================
---- linux-2.4.24-vanilla.orig/arch/arm/defconfig 2001-05-20 04:43:05.000000000 +0400
-+++ linux-2.4.24-vanilla/arch/arm/defconfig 2004-01-10 17:20:28.000000000 +0300
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_ARM=y
- # CONFIG_EISA is not set
- # CONFIG_SBUS is not set
-Index: linux-2.4.24-vanilla/arch/arm/kernel/calls.S
-===================================================================
---- linux-2.4.24-vanilla.orig/arch/arm/kernel/calls.S 2004-01-10 17:04:58.000000000 +0300
-+++ linux-2.4.24-vanilla/arch/arm/kernel/calls.S 2004-01-10 17:20:28.000000000 +0300
-@@ -240,18 +240,18 @@
- .long SYMBOL_NAME(sys_ni_syscall) /* Security */
- .long SYMBOL_NAME(sys_gettid)
- /* 225 */ .long SYMBOL_NAME(sys_readahead)
-- .long SYMBOL_NAME(sys_ni_syscall) /* setxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* lsetxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* fsetxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* getxattr */
--/* 230 */ .long SYMBOL_NAME(sys_ni_syscall) /* lgetxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* fgetxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* listxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* llistxattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* flistxattr */
--/* 235 */ .long SYMBOL_NAME(sys_ni_syscall) /* removexattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* lremovexattr */
-- .long SYMBOL_NAME(sys_ni_syscall) /* fremovexattr */
-+ .long SYMBOL_NAME(sys_setxattr)
-+ .long SYMBOL_NAME(sys_lsetxattr)
-+ .long SYMBOL_NAME(sys_fsetxattr)
-+ .long SYMBOL_NAME(sys_getxattr)
-+/* 230 */ .long SYMBOL_NAME(sys_lgetxattr)
-+ .long SYMBOL_NAME(sys_fgetxattr)
-+ .long SYMBOL_NAME(sys_listxattr)
-+ .long SYMBOL_NAME(sys_llistxattr)
-+ .long SYMBOL_NAME(sys_flistxattr)
-+/* 235 */ .long SYMBOL_NAME(sys_removexattr)
-+ .long SYMBOL_NAME(sys_lremovexattr)
-+ .long SYMBOL_NAME(sys_fremovexattr)
- .long SYMBOL_NAME(sys_tkill)
- .long SYMBOL_NAME(sys_ni_syscall) /* sendfile64 */
- /* 240 */ .long SYMBOL_NAME(sys_ni_syscall) /* futex */
-Index: linux-2.4.24-vanilla/arch/i386/defconfig
-===================================================================
---- linux-2.4.24-vanilla.orig/arch/i386/defconfig 2004-01-10 17:05:45.000000000 +0300
-+++ linux-2.4.24-vanilla/arch/i386/defconfig 2004-01-10 17:20:28.000000000 +0300
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_X86=y
- CONFIG_ISA=y
- # CONFIG_SBUS is not set
-Index: linux-2.4.24-vanilla/arch/ia64/defconfig
-===================================================================
---- linux-2.4.24-vanilla.orig/arch/ia64/defconfig 2004-01-10 17:05:52.000000000 +0300
-+++ linux-2.4.24-vanilla/arch/ia64/defconfig 2004-01-10 17:20:28.000000000 +0300
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
-
- #
- # Code maturity level options
-Index: linux-2.4.24-vanilla/arch/m68k/defconfig
-===================================================================
---- linux-2.4.24-vanilla.orig/arch/m68k/defconfig 2004-01-10 17:05:52.000000000 +0300
-+++ linux-2.4.24-vanilla/arch/m68k/defconfig 2004-01-10 17:20:28.000000000 +0300
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_UID16=y
-
- #
-Index: linux-2.4.24-vanilla/arch/mips/defconfig
-===================================================================
---- linux-2.4.24-vanilla.orig/arch/mips/defconfig 2004-01-10 17:04:59.000000000 +0300
-+++ linux-2.4.24-vanilla/arch/mips/defconfig 2004-01-10 17:20:28.000000000 +0300
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_MIPS=y
- CONFIG_MIPS32=y
- # CONFIG_MIPS64 is not set
-Index: linux-2.4.24-vanilla/arch/mips64/defconfig
-===================================================================
---- linux-2.4.24-vanilla.orig/arch/mips64/defconfig 2004-01-10 17:05:52.000000000 +0300
-+++ linux-2.4.24-vanilla/arch/mips64/defconfig 2004-01-10 17:20:28.000000000 +0300
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- CONFIG_MIPS=y
- # CONFIG_MIPS32 is not set
- CONFIG_MIPS64=y
-Index: linux-2.4.24-vanilla/arch/s390/defconfig
-===================================================================
---- linux-2.4.24-vanilla.orig/arch/s390/defconfig 2004-01-10 17:05:52.000000000 +0300
-+++ linux-2.4.24-vanilla/arch/s390/defconfig 2004-01-10 17:20:28.000000000 +0300
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- # CONFIG_ISA is not set
- # CONFIG_EISA is not set
- # CONFIG_MCA is not set
-Index: linux-2.4.24-vanilla/arch/s390/kernel/entry.S
-===================================================================
---- linux-2.4.24-vanilla.orig/arch/s390/kernel/entry.S 2004-01-10 17:04:39.000000000 +0300
-+++ linux-2.4.24-vanilla/arch/s390/kernel/entry.S 2004-01-10 17:20:28.000000000 +0300
-@@ -558,18 +558,18 @@
- .long sys_fcntl64
- .long sys_readahead
- .long sys_ni_syscall
-- .long sys_ni_syscall /* 224 - reserved for setxattr */
-- .long sys_ni_syscall /* 225 - reserved for lsetxattr */
-- .long sys_ni_syscall /* 226 - reserved for fsetxattr */
-- .long sys_ni_syscall /* 227 - reserved for getxattr */
-- .long sys_ni_syscall /* 228 - reserved for lgetxattr */
-- .long sys_ni_syscall /* 229 - reserved for fgetxattr */
-- .long sys_ni_syscall /* 230 - reserved for listxattr */
-- .long sys_ni_syscall /* 231 - reserved for llistxattr */
-- .long sys_ni_syscall /* 232 - reserved for flistxattr */
-- .long sys_ni_syscall /* 233 - reserved for removexattr */
-- .long sys_ni_syscall /* 234 - reserved for lremovexattr */
-- .long sys_ni_syscall /* 235 - reserved for fremovexattr */
-+ .long sys_setxattr
-+ .long sys_lsetxattr /* 225 */
-+ .long sys_fsetxattr
-+ .long sys_getxattr
-+ .long sys_lgetxattr
-+ .long sys_fgetxattr
-+ .long sys_listxattr /* 230 */
-+ .long sys_llistxattr
-+ .long sys_flistxattr
-+ .long sys_removexattr
-+ .long sys_lremovexattr
-+ .long sys_fremovexattr /* 235 */
- .long sys_gettid
- .long sys_tkill
- .rept 255-237
-Index: linux-2.4.24-vanilla/arch/s390x/defconfig
-===================================================================
---- linux-2.4.24-vanilla.orig/arch/s390x/defconfig 2004-01-10 17:05:52.000000000 +0300
-+++ linux-2.4.24-vanilla/arch/s390x/defconfig 2004-01-10 17:20:28.000000000 +0300
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
- # CONFIG_ISA is not set
- # CONFIG_EISA is not set
- # CONFIG_MCA is not set
-Index: linux-2.4.24-vanilla/arch/s390x/kernel/entry.S
-===================================================================
---- linux-2.4.24-vanilla.orig/arch/s390x/kernel/entry.S 2004-01-10 17:05:00.000000000 +0300
-+++ linux-2.4.24-vanilla/arch/s390x/kernel/entry.S 2004-01-10 17:20:28.000000000 +0300
-@@ -591,18 +591,18 @@
- .long SYSCALL(sys_ni_syscall,sys32_fcntl64_wrapper)
- .long SYSCALL(sys_readahead,sys32_readahead)
- .long SYSCALL(sys_ni_syscall,sys_ni_syscall)
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 224 - reserved for setxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 225 - reserved for lsetxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 226 - reserved for fsetxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 227 - reserved for getxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 228 - reserved for lgetxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 229 - reserved for fgetxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 230 - reserved for listxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 231 - reserved for llistxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 232 - reserved for flistxattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 233 - reserved for removexattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 234 - reserved for lremovexattr */
-- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 235 - reserved for fremovexattr */
-+ .long SYSCALL(sys_setxattr,sys32_setxattr_wrapper)
-+ .long SYSCALL(sys_lsetxattr,sys32_lsetxattr_wrapper) /* 225 */
-+ .long SYSCALL(sys_fsetxattr,sys32_fsetxattr_wrapper)
-+ .long SYSCALL(sys_getxattr,sys32_getxattr_wrapper)
-+ .long SYSCALL(sys_lgetxattr,sys32_lgetxattr_wrapper)
-+ .long SYSCALL(sys_fgetxattr,sys32_fgetxattr_wrapper)
-+ .long SYSCALL(sys_listxattr,sys32_listxattr_wrapper) /* 230 */
-+ .long SYSCALL(sys_llistxattr,sys32_llistxattr_wrapper)
-+ .long SYSCALL(sys_flistxattr,sys32_flistxattr_wrapper)
-+ .long SYSCALL(sys_removexattr,sys32_removexattr_wrapper)
-+ .long SYSCALL(sys_lremovexattr,sys32_lremovexattr_wrapper)
-+ .long SYSCALL(sys_fremovexattr,sys32_fremovexattr_wrapper)/* 235 */
- .long SYSCALL(sys_gettid,sys_gettid)
- .long SYSCALL(sys_tkill,sys_tkill)
- .rept 255-237
-Index: linux-2.4.24-vanilla/arch/s390x/kernel/wrapper32.S
-===================================================================
---- linux-2.4.24-vanilla.orig/arch/s390x/kernel/wrapper32.S 2004-01-10 17:05:00.000000000 +0300
-+++ linux-2.4.24-vanilla/arch/s390x/kernel/wrapper32.S 2004-01-10 17:20:28.000000000 +0300
-@@ -1098,6 +1098,98 @@
- llgfr %r4,%r4 # long
- jg sys32_fstat64 # branch to system call
-
-+ .globl sys32_setxattr_wrapper
-+sys32_setxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ lgfr %r6,%r6 # int
-+ jg sys_setxattr
-+
-+ .globl sys32_lsetxattr_wrapper
-+sys32_lsetxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ lgfr %r6,%r6 # int
-+ jg sys_lsetxattr
-+
-+ .globl sys32_fsetxattr_wrapper
-+sys32_fsetxattr_wrapper:
-+ lgfr %r2,%r2 # int
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ lgfr %r6,%r6 # int
-+ jg sys_fsetxattr
-+
-+ .globl sys32_getxattr_wrapper
-+sys32_getxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ jg sys_getxattr
-+
-+ .globl sys32_lgetxattr_wrapper
-+sys32_lgetxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ jg sys_lgetxattr
-+
-+ .globl sys32_fgetxattr_wrapper
-+sys32_fgetxattr_wrapper:
-+ lgfr %r2,%r2 # int
-+ llgtr %r3,%r3 # char *
-+ llgtr %r4,%r4 # void *
-+ llgfr %r5,%r5 # size_t
-+ jg sys_fgetxattr
-+
-+ .globl sys32_listxattr_wrapper
-+sys32_listxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgfr %r4,%r4 # size_t
-+ jg sys_listxattr
-+
-+ .globl sys32_llistxattr_wrapper
-+sys32_llistxattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ llgfr %r4,%r4 # size_t
-+ jg sys_llistxattr
-+
-+ .globl sys32_flistxattr_wrapper
-+sys32_flistxattr_wrapper:
-+ lgfr %r2,%r2 # int
-+ llgtr %r3,%r3 # char *
-+ llgfr %r4,%r4 # size_t
-+ jg sys_flistxattr
-+
-+ .globl sys32_removexattr_wrapper
-+sys32_removexattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ jg sys_removexattr
-+
-+ .globl sys32_lremovexattr_wrapper
-+sys32_lremovexattr_wrapper:
-+ llgtr %r2,%r2 # char *
-+ llgtr %r3,%r3 # char *
-+ jg sys_lremovexattr
-+
-+ .globl sys32_fremovexattr_wrapper
-+sys32_fremovexattr_wrapper:
-+ lgfr %r2,%r2 # int
-+ llgtr %r3,%r3 # char *
-+ jg sys_fremovexattr
-+
-+
-+
- .globl sys32_stime_wrapper
- sys32_stime_wrapper:
- llgtr %r2,%r2 # int *
-Index: linux-2.4.24-vanilla/arch/sparc64/defconfig
-===================================================================
---- linux-2.4.24-vanilla.orig/arch/sparc64/defconfig 2004-01-10 17:05:52.000000000 +0300
-+++ linux-2.4.24-vanilla/arch/sparc64/defconfig 2004-01-10 17:20:28.000000000 +0300
-@@ -1,6 +1,13 @@
- #
- # Automatically generated make config: don't edit
- #
-+CONFIG_EXT3_FS_XATTR=y
-+# CONFIG_EXT3_FS_XATTR_SHARING is not set
-+# CONFIG_EXT3_FS_XATTR_USER is not set
-+# CONFIG_EXT2_FS_XATTR is not set
-+# CONFIG_EXT2_FS_XATTR_SHARING is not set
-+# CONFIG_EXT2_FS_XATTR_USER is not set
-+# CONFIG_FS_MBCACHE is not set
-
- #
- # Code maturity level options
-Index: linux-2.4.24-vanilla/fs/Config.in
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/Config.in 2004-01-10 17:05:55.000000000 +0300
-+++ linux-2.4.24-vanilla/fs/Config.in 2004-01-10 17:20:28.000000000 +0300
-@@ -29,6 +29,11 @@
- dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL
-
- tristate 'Ext3 journalling file system support' CONFIG_EXT3_FS
-+dep_mbool ' Ext3 extended attributes' CONFIG_EXT3_FS_XATTR $CONFIG_EXT3_FS
-+dep_bool ' Ext3 extended attribute block sharing' \
-+ CONFIG_EXT3_FS_XATTR_SHARING $CONFIG_EXT3_FS_XATTR
-+dep_bool ' Ext3 extended user attributes' \
-+ CONFIG_EXT3_FS_XATTR_USER $CONFIG_EXT3_FS_XATTR
- # CONFIG_JBD could be its own option (even modular), but until there are
- # other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS
- # dep_tristate ' Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS
-@@ -92,6 +97,11 @@
- tristate 'ROM file system support' CONFIG_ROMFS_FS
-
- tristate 'Second extended fs support' CONFIG_EXT2_FS
-+dep_mbool ' Ext2 extended attributes' CONFIG_EXT2_FS_XATTR $CONFIG_EXT2_FS
-+dep_bool ' Ext2 extended attribute block sharing' \
-+ CONFIG_EXT2_FS_XATTR_SHARING $CONFIG_EXT2_FS_XATTR
-+dep_bool ' Ext2 extended user attributes' \
-+ CONFIG_EXT2_FS_XATTR_USER $CONFIG_EXT2_FS_XATTR
-
- tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS
-
-@@ -164,6 +174,10 @@
- define_tristate CONFIG_ZISOFS_FS n
- fi
-
-+# Meta block cache for Extended Attributes (ext2/ext3)
-+#tristate 'Meta block cache' CONFIG_FS_MBCACHE
-+define_tristate CONFIG_FS_MBCACHE y
-+
- mainmenu_option next_comment
- comment 'Partition Types'
- source fs/partitions/Config.in
-Index: linux-2.4.24-vanilla/fs/Makefile
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/Makefile 2004-01-10 17:11:48.000000000 +0300
-+++ linux-2.4.24-vanilla/fs/Makefile 2004-01-10 17:20:28.000000000 +0300
-@@ -77,6 +77,9 @@
-
- obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o
-
-+export-objs += mbcache.o
-+obj-$(CONFIG_FS_MBCACHE) += mbcache.o
-+
- # persistent filesystems
- obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
-
-Index: linux-2.4.24-vanilla/fs/ext2/Makefile
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/ext2/Makefile 2001-10-11 19:05:18.000000000 +0400
-+++ linux-2.4.24-vanilla/fs/ext2/Makefile 2004-01-10 17:20:28.000000000 +0300
-@@ -13,4 +13,8 @@
- ioctl.o namei.o super.o symlink.o
- obj-m := $(O_TARGET)
-
-+export-objs += xattr.o
-+obj-$(CONFIG_EXT2_FS_XATTR) += xattr.o
-+obj-$(CONFIG_EXT2_FS_XATTR_USER) += xattr_user.o
-+
- include $(TOPDIR)/Rules.make
-Index: linux-2.4.24-vanilla/fs/ext2/file.c
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/ext2/file.c 2001-10-11 19:05:18.000000000 +0400
-+++ linux-2.4.24-vanilla/fs/ext2/file.c 2004-01-10 17:20:28.000000000 +0300
-@@ -20,6 +20,7 @@
-
- #include <linux/fs.h>
- #include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
- #include <linux/sched.h>
-
- /*
-@@ -51,4 +52,8 @@
-
- struct inode_operations ext2_file_inode_operations = {
- truncate: ext2_truncate,
-+ setxattr: ext2_setxattr,
-+ getxattr: ext2_getxattr,
-+ listxattr: ext2_listxattr,
-+ removexattr: ext2_removexattr,
- };
-Index: linux-2.4.24-vanilla/fs/ext2/ialloc.c
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/ext2/ialloc.c 2004-01-10 17:04:42.000000000 +0300
-+++ linux-2.4.24-vanilla/fs/ext2/ialloc.c 2004-01-10 17:20:28.000000000 +0300
-@@ -15,6 +15,7 @@
- #include <linux/config.h>
- #include <linux/fs.h>
- #include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
- #include <linux/locks.h>
- #include <linux/quotaops.h>
-
-@@ -167,6 +168,7 @@
- */
- if (!is_bad_inode(inode)) {
- /* Quota is already initialized in iput() */
-+ ext2_xattr_delete_inode(inode);
- DQUOT_FREE_INODE(inode);
- DQUOT_DROP(inode);
- }
-Index: linux-2.4.24-vanilla/fs/ext2/inode.c
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/ext2/inode.c 2004-01-10 17:04:42.000000000 +0300
-+++ linux-2.4.24-vanilla/fs/ext2/inode.c 2004-01-10 17:20:28.000000000 +0300
-@@ -39,6 +39,18 @@
- static int ext2_update_inode(struct inode * inode, int do_sync);
-
- /*
-+ * Test whether an inode is a fast symlink.
-+ */
-+static inline int ext2_inode_is_fast_symlink(struct inode *inode)
-+{
-+ int ea_blocks = inode->u.ext2_i.i_file_acl ?
-+ (inode->i_sb->s_blocksize >> 9) : 0;
-+
-+ return (S_ISLNK(inode->i_mode) &&
-+ inode->i_blocks - ea_blocks == 0);
-+}
-+
-+/*
- * Called at each iput()
- */
- void ext2_put_inode (struct inode * inode)
-@@ -53,9 +65,7 @@
- {
- lock_kernel();
-
-- if (is_bad_inode(inode) ||
-- inode->i_ino == EXT2_ACL_IDX_INO ||
-- inode->i_ino == EXT2_ACL_DATA_INO)
-+ if (is_bad_inode(inode))
- goto no_delete;
- inode->u.ext2_i.i_dtime = CURRENT_TIME;
- mark_inode_dirty(inode);
-@@ -801,6 +811,8 @@
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return;
-+ if (ext2_inode_is_fast_symlink(inode))
-+ return;
- if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
- return;
-
-@@ -903,8 +915,7 @@
- unsigned long offset;
- struct ext2_group_desc * gdp;
-
-- if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO &&
-- inode->i_ino != EXT2_ACL_DATA_INO &&
-+ if ((inode->i_ino != EXT2_ROOT_INO &&
- inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) ||
- inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
- ext2_error (inode->i_sb, "ext2_read_inode",
-@@ -989,10 +1000,7 @@
- for (block = 0; block < EXT2_N_BLOCKS; block++)
- inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
-
-- if (inode->i_ino == EXT2_ACL_IDX_INO ||
-- inode->i_ino == EXT2_ACL_DATA_INO)
-- /* Nothing to do */ ;
-- else if (S_ISREG(inode->i_mode)) {
-+ if (S_ISREG(inode->i_mode)) {
- inode->i_op = &ext2_file_inode_operations;
- inode->i_fop = &ext2_file_operations;
- inode->i_mapping->a_ops = &ext2_aops;
-@@ -1001,15 +1009,17 @@
- inode->i_fop = &ext2_dir_operations;
- inode->i_mapping->a_ops = &ext2_aops;
- } else if (S_ISLNK(inode->i_mode)) {
-- if (!inode->i_blocks)
-+ if (ext2_inode_is_fast_symlink(inode))
- inode->i_op = &ext2_fast_symlink_inode_operations;
- else {
-- inode->i_op = &page_symlink_inode_operations;
-+ inode->i_op = &ext2_symlink_inode_operations;
- inode->i_mapping->a_ops = &ext2_aops;
- }
-- } else
-+ } else {
-+ inode->i_op = &ext2_special_inode_operations;
- init_special_inode(inode, inode->i_mode,
- le32_to_cpu(raw_inode->i_block[0]));
-+ }
- brelse (bh);
- inode->i_attr_flags = 0;
- ext2_set_inode_flags(inode);
-Index: linux-2.4.24-vanilla/fs/ext2/namei.c
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/ext2/namei.c 2001-10-04 09:57:36.000000000 +0400
-+++ linux-2.4.24-vanilla/fs/ext2/namei.c 2004-01-10 17:20:28.000000000 +0300
-@@ -31,6 +31,7 @@
-
- #include <linux/fs.h>
- #include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
- #include <linux/pagemap.h>
-
- /*
-@@ -136,7 +137,7 @@
-
- if (l > sizeof (inode->u.ext2_i.i_data)) {
- /* slow symlink */
-- inode->i_op = &page_symlink_inode_operations;
-+ inode->i_op = &ext2_symlink_inode_operations;
- inode->i_mapping->a_ops = &ext2_aops;
- err = block_symlink(inode, symname, l);
- if (err)
-@@ -345,4 +346,15 @@
- rmdir: ext2_rmdir,
- mknod: ext2_mknod,
- rename: ext2_rename,
-+ setxattr: ext2_setxattr,
-+ getxattr: ext2_getxattr,
-+ listxattr: ext2_listxattr,
-+ removexattr: ext2_removexattr,
-+};
-+
-+struct inode_operations ext2_special_inode_operations = {
-+ setxattr: ext2_setxattr,
-+ getxattr: ext2_getxattr,
-+ listxattr: ext2_listxattr,
-+ removexattr: ext2_removexattr,
- };
-Index: linux-2.4.24-vanilla/fs/ext2/super.c
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/ext2/super.c 2003-05-16 05:29:12.000000000 +0400
-+++ linux-2.4.24-vanilla/fs/ext2/super.c 2004-01-10 17:20:28.000000000 +0300
-@@ -21,6 +21,7 @@
- #include <linux/string.h>
- #include <linux/fs.h>
- #include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
- #include <linux/slab.h>
- #include <linux/init.h>
- #include <linux/locks.h>
-@@ -125,6 +126,7 @@
- int db_count;
- int i;
-
-+ ext2_xattr_put_super(sb);
- if (!(sb->s_flags & MS_RDONLY)) {
- struct ext2_super_block *es = EXT2_SB(sb)->s_es;
-
-@@ -175,6 +177,13 @@
- this_char = strtok (NULL, ",")) {
- if ((value = strchr (this_char, '=')) != NULL)
- *value++ = 0;
-+#ifdef CONFIG_EXT2_FS_XATTR_USER
-+ if (!strcmp (this_char, "user_xattr"))
-+ set_opt (*mount_options, XATTR_USER);
-+ else if (!strcmp (this_char, "nouser_xattr"))
-+ clear_opt (*mount_options, XATTR_USER);
-+ else
-+#endif
- if (!strcmp (this_char, "bsddf"))
- clear_opt (*mount_options, MINIX_DF);
- else if (!strcmp (this_char, "nouid32")) {
-@@ -424,6 +433,9 @@
- blocksize = BLOCK_SIZE;
-
- sb->u.ext2_sb.s_mount_opt = 0;
-+#ifdef CONFIG_EXT2_FS_XATTR_USER
-+ /* set_opt (sb->u.ext2_sb.s_mount_opt, XATTR_USER); */
-+#endif
- if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
- &sb->u.ext2_sb.s_mount_opt)) {
- return NULL;
-@@ -813,12 +825,27 @@
-
- static int __init init_ext2_fs(void)
- {
-- return register_filesystem(&ext2_fs_type);
-+ int error = init_ext2_xattr();
-+ if (error)
-+ return error;
-+ error = init_ext2_xattr_user();
-+ if (error)
-+ goto fail;
-+ error = register_filesystem(&ext2_fs_type);
-+ if (!error)
-+ return 0;
-+
-+ exit_ext2_xattr_user();
-+fail:
-+ exit_ext2_xattr();
-+ return error;
- }
-
- static void __exit exit_ext2_fs(void)
- {
- unregister_filesystem(&ext2_fs_type);
-+ exit_ext2_xattr_user();
-+ exit_ext2_xattr();
- }
-
- EXPORT_NO_SYMBOLS;
-Index: linux-2.4.24-vanilla/fs/ext2/symlink.c
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/ext2/symlink.c 2000-09-28 00:41:33.000000000 +0400
-+++ linux-2.4.24-vanilla/fs/ext2/symlink.c 2004-01-10 17:20:28.000000000 +0300
-@@ -19,6 +19,7 @@
-
- #include <linux/fs.h>
- #include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
-
- static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen)
- {
-@@ -32,7 +33,20 @@
- return vfs_follow_link(nd, s);
- }
-
-+struct inode_operations ext2_symlink_inode_operations = {
-+ readlink: page_readlink,
-+ follow_link: page_follow_link,
-+ setxattr: ext2_setxattr,
-+ getxattr: ext2_getxattr,
-+ listxattr: ext2_listxattr,
-+ removexattr: ext2_removexattr,
-+};
-+
- struct inode_operations ext2_fast_symlink_inode_operations = {
- readlink: ext2_readlink,
- follow_link: ext2_follow_link,
-+ setxattr: ext2_setxattr,
-+ getxattr: ext2_getxattr,
-+ listxattr: ext2_listxattr,
-+ removexattr: ext2_removexattr,
- };
-Index: linux-2.4.24-vanilla/fs/ext2/xattr.c
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/ext2/xattr.c 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.24-vanilla/fs/ext2/xattr.c 2004-01-10 17:20:28.000000000 +0300
-@@ -0,0 +1,1212 @@
-+/*
-+ * linux/fs/ext2/xattr.c
-+ *
-+ * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ *
-+ * Fix by Harrison Xing <harrison@mountainviewdata.com>.
-+ * Extended attributes for symlinks and special files added per
-+ * suggestion of Luka Renko <luka.renko@hermes.si>.
-+ */
-+
-+/*
-+ * Extended attributes are stored on disk blocks allocated outside of
-+ * any inode. The i_file_acl field is then made to point to this allocated
-+ * block. If all extended attributes of an inode are identical, these
-+ * inodes may share the same extended attribute block. Such situations
-+ * are automatically detected by keeping a cache of recent attribute block
-+ * numbers and hashes over the block's contents in memory.
-+ *
-+ *
-+ * Extended attribute block layout:
-+ *
-+ * +------------------+
-+ * | header |
-+ * | entry 1 | |
-+ * | entry 2 | | growing downwards
-+ * | entry 3 | v
-+ * | four null bytes |
-+ * | . . . |
-+ * | value 1 | ^
-+ * | value 3 | | growing upwards
-+ * | value 2 | |
-+ * +------------------+
-+ *
-+ * The block header is followed by multiple entry descriptors. These entry
-+ * descriptors are variable in size, and alligned to EXT2_XATTR_PAD
-+ * byte boundaries. The entry descriptors are sorted by attribute name,
-+ * so that two extended attribute blocks can be compared efficiently.
-+ *
-+ * Attribute values are aligned to the end of the block, stored in
-+ * no specific order. They are also padded to EXT2_XATTR_PAD byte
-+ * boundaries. No additional gaps are left between them.
-+ *
-+ * Locking strategy
-+ * ----------------
-+ * The VFS already holds the BKL and the inode->i_sem semaphore when any of
-+ * the xattr inode operations are called, so we are guaranteed that only one
-+ * processes accesses extended attributes of an inode at any time.
-+ *
-+ * For writing we also grab the ext2_xattr_sem semaphore. This ensures that
-+ * only a single process is modifying an extended attribute block, even
-+ * if the block is shared among inodes.
-+ *
-+ * Note for porting to 2.5
-+ * -----------------------
-+ * The BKL will no longer be held in the xattr inode operations.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/locks.h>
-+#include <linux/slab.h>
-+#include <linux/fs.h>
-+#include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
-+#include <linux/mbcache.h>
-+#include <linux/quotaops.h>
-+#include <asm/semaphore.h>
-+#include <linux/compatmac.h>
-+
-+/* These symbols may be needed by a module. */
-+EXPORT_SYMBOL(ext2_xattr_register);
-+EXPORT_SYMBOL(ext2_xattr_unregister);
-+EXPORT_SYMBOL(ext2_xattr_get);
-+EXPORT_SYMBOL(ext2_xattr_list);
-+EXPORT_SYMBOL(ext2_xattr_set);
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-+# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
-+#endif
-+
-+#define HDR(bh) ((struct ext2_xattr_header *)((bh)->b_data))
-+#define ENTRY(ptr) ((struct ext2_xattr_entry *)(ptr))
-+#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
-+#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
-+
-+#ifdef EXT2_XATTR_DEBUG
-+# define ea_idebug(inode, f...) do { \
-+ printk(KERN_DEBUG "inode %s:%ld: ", \
-+ kdevname(inode->i_dev), inode->i_ino); \
-+ printk(f); \
-+ printk("\n"); \
-+ } while (0)
-+# define ea_bdebug(bh, f...) do { \
-+ printk(KERN_DEBUG "block %s:%ld: ", \
-+ kdevname(bh->b_dev), bh->b_blocknr); \
-+ printk(f); \
-+ printk("\n"); \
-+ } while (0)
-+#else
-+# define ea_idebug(f...)
-+# define ea_bdebug(f...)
-+#endif
-+
-+static int ext2_xattr_set2(struct inode *, struct buffer_head *,
-+ struct ext2_xattr_header *);
-+
-+#ifdef CONFIG_EXT2_FS_XATTR_SHARING
-+
-+static int ext2_xattr_cache_insert(struct buffer_head *);
-+static struct buffer_head *ext2_xattr_cache_find(struct inode *,
-+ struct ext2_xattr_header *);
-+static void ext2_xattr_cache_remove(struct buffer_head *);
-+static void ext2_xattr_rehash(struct ext2_xattr_header *,
-+ struct ext2_xattr_entry *);
-+
-+static struct mb_cache *ext2_xattr_cache;
-+
-+#else
-+# define ext2_xattr_cache_insert(bh) 0
-+# define ext2_xattr_cache_find(inode, header) NULL
-+# define ext2_xattr_cache_remove(bh) while(0) {}
-+# define ext2_xattr_rehash(header, entry) while(0) {}
-+#endif
-+
-+/*
-+ * If a file system does not share extended attributes among inodes,
-+ * we should not need the ext2_xattr_sem semaphore. However, the
-+ * filesystem may still contain shared blocks, so we always take
-+ * the lock.
-+ */
-+
-+DECLARE_MUTEX(ext2_xattr_sem);
-+
-+static inline int
-+ext2_xattr_new_block(struct inode *inode, int * errp, int force)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ int goal = le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block) +
-+ EXT2_I(inode)->i_block_group * EXT2_BLOCKS_PER_GROUP(sb);
-+
-+ /* How can we enforce the allocation? */
-+ int block = ext2_new_block(inode, goal, 0, 0, errp);
-+#ifdef OLD_QUOTAS
-+ if (!*errp)
-+ inode->i_blocks += inode->i_sb->s_blocksize >> 9;
-+#endif
-+ return block;
-+}
-+
-+static inline int
-+ext2_xattr_quota_alloc(struct inode *inode, int force)
-+{
-+ /* How can we enforce the allocation? */
-+#ifdef OLD_QUOTAS
-+ int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1);
-+ if (!error)
-+ inode->i_blocks += inode->i_sb->s_blocksize >> 9;
-+#else
-+ int error = DQUOT_ALLOC_BLOCK(inode, 1);
-+#endif
-+ return error;
-+}
-+
-+#ifdef OLD_QUOTAS
-+
-+static inline void
-+ext2_xattr_quota_free(struct inode *inode)
-+{
-+ DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
-+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
-+}
-+
-+static inline void
-+ext2_xattr_free_block(struct inode * inode, unsigned long block)
-+{
-+ ext2_free_blocks(inode, block, 1);
-+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
-+}
-+
-+#else
-+# define ext2_xattr_quota_free(inode) \
-+ DQUOT_FREE_BLOCK(inode, 1)
-+# define ext2_xattr_free_block(inode, block) \
-+ ext2_free_blocks(inode, block, 1)
-+#endif
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
-+
-+static inline struct buffer_head *
-+sb_bread(struct super_block *sb, int block)
-+{
-+ return bread(sb->s_dev, block, sb->s_blocksize);
-+}
-+
-+static inline struct buffer_head *
-+sb_getblk(struct super_block *sb, int block)
-+{
-+ return getblk(sb->s_dev, block, sb->s_blocksize);
-+}
-+
-+#endif
-+
-+struct ext2_xattr_handler *ext2_xattr_handlers[EXT2_XATTR_INDEX_MAX];
-+rwlock_t ext2_handler_lock = RW_LOCK_UNLOCKED;
-+
-+int
-+ext2_xattr_register(int name_index, struct ext2_xattr_handler *handler)
-+{
-+ int error = -EINVAL;
-+
-+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
-+ write_lock(&ext2_handler_lock);
-+ if (!ext2_xattr_handlers[name_index-1]) {
-+ ext2_xattr_handlers[name_index-1] = handler;
-+ error = 0;
-+ }
-+ write_unlock(&ext2_handler_lock);
-+ }
-+ return error;
-+}
-+
-+void
-+ext2_xattr_unregister(int name_index, struct ext2_xattr_handler *handler)
-+{
-+ if (name_index > 0 || name_index <= EXT2_XATTR_INDEX_MAX) {
-+ write_lock(&ext2_handler_lock);
-+ ext2_xattr_handlers[name_index-1] = NULL;
-+ write_unlock(&ext2_handler_lock);
-+ }
-+}
-+
-+static inline const char *
-+strcmp_prefix(const char *a, const char *a_prefix)
-+{
-+ while (*a_prefix && *a == *a_prefix) {
-+ a++;
-+ a_prefix++;
-+ }
-+ return *a_prefix ? NULL : a;
-+}
-+
-+/*
-+ * Decode the extended attribute name, and translate it into
-+ * the name_index and name suffix.
-+ */
-+static struct ext2_xattr_handler *
-+ext2_xattr_resolve_name(const char **name)
-+{
-+ struct ext2_xattr_handler *handler = NULL;
-+ int i;
-+
-+ if (!*name)
-+ return NULL;
-+ read_lock(&ext2_handler_lock);
-+ for (i=0; i<EXT2_XATTR_INDEX_MAX; i++) {
-+ if (ext2_xattr_handlers[i]) {
-+ const char *n = strcmp_prefix(*name,
-+ ext2_xattr_handlers[i]->prefix);
-+ if (n) {
-+ handler = ext2_xattr_handlers[i];
-+ *name = n;
-+ break;
-+ }
-+ }
-+ }
-+ read_unlock(&ext2_handler_lock);
-+ return handler;
-+}
-+
-+static inline struct ext2_xattr_handler *
-+ext2_xattr_handler(int name_index)
-+{
-+ struct ext2_xattr_handler *handler = NULL;
-+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) {
-+ read_lock(&ext2_handler_lock);
-+ handler = ext2_xattr_handlers[name_index-1];
-+ read_unlock(&ext2_handler_lock);
-+ }
-+ return handler;
-+}
-+
-+/*
-+ * Inode operation getxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ * BKL held [before 2.5.x]
-+ */
-+ssize_t
-+ext2_getxattr(struct dentry *dentry, const char *name,
-+ void *buffer, size_t size)
-+{
-+ struct ext2_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ handler = ext2_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -ENOTSUP;
-+ return handler->get(inode, name, buffer, size);
-+}
-+
-+/*
-+ * Inode operation listxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ * BKL held [before 2.5.x]
-+ */
-+ssize_t
-+ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
-+{
-+ return ext2_xattr_list(dentry->d_inode, buffer, size);
-+}
-+
-+/*
-+ * Inode operation setxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ * BKL held [before 2.5.x]
-+ */
-+int
-+ext2_setxattr(struct dentry *dentry, const char *name,
-+ const void *value, size_t size, int flags)
-+{
-+ struct ext2_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ if (size == 0)
-+ value = ""; /* empty EA, do not remove */
-+ handler = ext2_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -ENOTSUP;
-+ return handler->set(inode, name, value, size, flags);
-+}
-+
-+/*
-+ * Inode operation removexattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ * BKL held [before 2.5.x]
-+ */
-+int
-+ext2_removexattr(struct dentry *dentry, const char *name)
-+{
-+ struct ext2_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ handler = ext2_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -ENOTSUP;
-+ return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
-+}
-+
-+/*
-+ * ext2_xattr_get()
-+ *
-+ * Copy an extended attribute into the buffer
-+ * provided, or compute the buffer size required.
-+ * Buffer is NULL to compute the size of the buffer required.
-+ *
-+ * Returns a negative error number on failure, or the number of bytes
-+ * used / required on success.
-+ */
-+int
-+ext2_xattr_get(struct inode *inode, int name_index, const char *name,
-+ void *buffer, size_t buffer_size)
-+{
-+ struct buffer_head *bh = NULL;
-+ struct ext2_xattr_entry *entry;
-+ unsigned int block, size;
-+ char *end;
-+ int name_len, error;
-+
-+ ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
-+ name_index, name, buffer, (long)buffer_size);
-+
-+ if (name == NULL)
-+ return -EINVAL;
-+ if (!EXT2_I(inode)->i_file_acl)
-+ return -ENOATTR;
-+ block = EXT2_I(inode)->i_file_acl;
-+ ea_idebug(inode, "reading block %d", block);
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh)
-+ return -EIO;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
-+ end = bh->b_data + bh->b_size;
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext2_error(inode->i_sb, "ext2_xattr_get",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* find named attribute */
-+ name_len = strlen(name);
-+
-+ error = -ERANGE;
-+ if (name_len > 255)
-+ goto cleanup;
-+ entry = FIRST_ENTRY(bh);
-+ while (!IS_LAST_ENTRY(entry)) {
-+ struct ext2_xattr_entry *next =
-+ EXT2_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (name_index == entry->e_name_index &&
-+ name_len == entry->e_name_len &&
-+ memcmp(name, entry->e_name, name_len) == 0)
-+ goto found;
-+ entry = next;
-+ }
-+ /* Check the remaining name entries */
-+ while (!IS_LAST_ENTRY(entry)) {
-+ struct ext2_xattr_entry *next =
-+ EXT2_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ entry = next;
-+ }
-+ if (ext2_xattr_cache_insert(bh))
-+ ea_idebug(inode, "cache insert failed");
-+ error = -ENOATTR;
-+ goto cleanup;
-+found:
-+ /* check the buffer size */
-+ if (entry->e_value_block != 0)
-+ goto bad_block;
-+ size = le32_to_cpu(entry->e_value_size);
-+ if (size > inode->i_sb->s_blocksize ||
-+ le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
-+ goto bad_block;
-+
-+ if (ext2_xattr_cache_insert(bh))
-+ ea_idebug(inode, "cache insert failed");
-+ if (buffer) {
-+ error = -ERANGE;
-+ if (size > buffer_size)
-+ goto cleanup;
-+ /* return value of attribute */
-+ memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
-+ size);
-+ }
-+ error = size;
-+
-+cleanup:
-+ brelse(bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * ext2_xattr_list()
-+ *
-+ * Copy a list of attribute names into the buffer
-+ * provided, or compute the buffer size required.
-+ * Buffer is NULL to compute the size of the buffer required.
-+ *
-+ * Returns a negative error number on failure, or the number of bytes
-+ * used / required on success.
-+ */
-+int
-+ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
-+{
-+ struct buffer_head *bh = NULL;
-+ struct ext2_xattr_entry *entry;
-+ unsigned int block, size = 0;
-+ char *buf, *end;
-+ int error;
-+
-+ ea_idebug(inode, "buffer=%p, buffer_size=%ld",
-+ buffer, (long)buffer_size);
-+
-+ if (!EXT2_I(inode)->i_file_acl)
-+ return 0;
-+ block = EXT2_I(inode)->i_file_acl;
-+ ea_idebug(inode, "reading block %d", block);
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh)
-+ return -EIO;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
-+ end = bh->b_data + bh->b_size;
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext2_error(inode->i_sb, "ext2_xattr_list",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* compute the size required for the list of attribute names */
-+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
-+ entry = EXT2_XATTR_NEXT(entry)) {
-+ struct ext2_xattr_handler *handler;
-+ struct ext2_xattr_entry *next =
-+ EXT2_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+
-+ handler = ext2_xattr_handler(entry->e_name_index);
-+ if (handler)
-+ size += handler->list(NULL, inode, entry->e_name,
-+ entry->e_name_len);
-+ }
-+
-+ if (ext2_xattr_cache_insert(bh))
-+ ea_idebug(inode, "cache insert failed");
-+ if (!buffer) {
-+ error = size;
-+ goto cleanup;
-+ } else {
-+ error = -ERANGE;
-+ if (size > buffer_size)
-+ goto cleanup;
-+ }
-+
-+ /* list the attribute names */
-+ buf = buffer;
-+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
-+ entry = EXT2_XATTR_NEXT(entry)) {
-+ struct ext2_xattr_handler *handler;
-+
-+ handler = ext2_xattr_handler(entry->e_name_index);
-+ if (handler)
-+ buf += handler->list(buf, inode, entry->e_name,
-+ entry->e_name_len);
-+ }
-+ error = size;
-+
-+cleanup:
-+ brelse(bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * If the EXT2_FEATURE_COMPAT_EXT_ATTR feature of this file system is
-+ * not set, set it.
-+ */
-+static void ext2_xattr_update_super_block(struct super_block *sb)
-+{
-+ if (EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_EXT_ATTR))
-+ return;
-+
-+ lock_super(sb);
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-+ EXT2_SB(sb)->s_feature_compat |= EXT2_FEATURE_COMPAT_EXT_ATTR;
-+#endif
-+ EXT2_SB(sb)->s_es->s_feature_compat |=
-+ cpu_to_le32(EXT2_FEATURE_COMPAT_EXT_ATTR);
-+ sb->s_dirt = 1;
-+ mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
-+ unlock_super(sb);
-+}
-+
-+/*
-+ * ext2_xattr_set()
-+ *
-+ * Create, replace or remove an extended attribute for this inode. Buffer
-+ * is NULL to remove an existing extended attribute, and non-NULL to
-+ * either replace an existing extended attribute, or create a new extended
-+ * attribute. The flags XATTR_REPLACE and XATTR_CREATE
-+ * specify that an extended attribute must exist and must not exist
-+ * previous to the call, respectively.
-+ *
-+ * Returns 0, or a negative error number on failure.
-+ */
-+int
-+ext2_xattr_set(struct inode *inode, int name_index, const char *name,
-+ const void *value, size_t value_len, int flags)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct buffer_head *bh = NULL;
-+ struct ext2_xattr_header *header = NULL;
-+ struct ext2_xattr_entry *here, *last;
-+ unsigned int name_len;
-+ int block = EXT2_I(inode)->i_file_acl;
-+ int min_offs = sb->s_blocksize, not_found = 1, free, error;
-+ char *end;
-+
-+ /*
-+ * header -- Points either into bh, or to a temporarily
-+ * allocated buffer.
-+ * here -- The named entry found, or the place for inserting, within
-+ * the block pointed to by header.
-+ * last -- Points right after the last named entry within the block
-+ * pointed to by header.
-+ * min_offs -- The offset of the first value (values are aligned
-+ * towards the end of the block).
-+ * end -- Points right after the block pointed to by header.
-+ */
-+
-+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
-+ name_index, name, value, (long)value_len);
-+
-+ if (IS_RDONLY(inode))
-+ return -EROFS;
-+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-+ return -EPERM;
-+ if (value == NULL)
-+ value_len = 0;
-+ if (name == NULL)
-+ return -EINVAL;
-+ name_len = strlen(name);
-+ if (name_len > 255 || value_len > sb->s_blocksize)
-+ return -ERANGE;
-+ down(&ext2_xattr_sem);
-+
-+ if (block) {
-+ /* The inode already has an extended attribute block. */
-+
-+ bh = sb_bread(sb, block);
-+ error = -EIO;
-+ if (!bh)
-+ goto cleanup;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)),
-+ le32_to_cpu(HDR(bh)->h_refcount));
-+ header = HDR(bh);
-+ end = bh->b_data + bh->b_size;
-+ if (header->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
-+ header->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext2_error(sb, "ext2_xattr_set",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* Find the named attribute. */
-+ here = FIRST_ENTRY(bh);
-+ while (!IS_LAST_ENTRY(here)) {
-+ struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(here);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (!here->e_value_block && here->e_value_size) {
-+ int offs = le16_to_cpu(here->e_value_offs);
-+ if (offs < min_offs)
-+ min_offs = offs;
-+ }
-+ not_found = name_index - here->e_name_index;
-+ if (!not_found)
-+ not_found = name_len - here->e_name_len;
-+ if (!not_found)
-+ not_found = memcmp(name, here->e_name,name_len);
-+ if (not_found <= 0)
-+ break;
-+ here = next;
-+ }
-+ last = here;
-+ /* We still need to compute min_offs and last. */
-+ while (!IS_LAST_ENTRY(last)) {
-+ struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (!last->e_value_block && last->e_value_size) {
-+ int offs = le16_to_cpu(last->e_value_offs);
-+ if (offs < min_offs)
-+ min_offs = offs;
-+ }
-+ last = next;
-+ }
-+
-+ /* Check whether we have enough space left. */
-+ free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
-+ } else {
-+ /* We will use a new extended attribute block. */
-+ free = sb->s_blocksize -
-+ sizeof(struct ext2_xattr_header) - sizeof(__u32);
-+ here = last = NULL; /* avoid gcc uninitialized warning. */
-+ }
-+
-+ if (not_found) {
-+ /* Request to remove a nonexistent attribute? */
-+ error = -ENOATTR;
-+ if (flags & XATTR_REPLACE)
-+ goto cleanup;
-+ error = 0;
-+ if (value == NULL)
-+ goto cleanup;
-+ else
-+ free -= EXT2_XATTR_LEN(name_len);
-+ } else {
-+ /* Request to create an existing attribute? */
-+ error = -EEXIST;
-+ if (flags & XATTR_CREATE)
-+ goto cleanup;
-+ if (!here->e_value_block && here->e_value_size) {
-+ unsigned int size = le32_to_cpu(here->e_value_size);
-+
-+ if (le16_to_cpu(here->e_value_offs) + size >
-+ sb->s_blocksize || size > sb->s_blocksize)
-+ goto bad_block;
-+ free += EXT2_XATTR_SIZE(size);
-+ }
-+ }
-+ free -= EXT2_XATTR_SIZE(value_len);
-+ error = -ENOSPC;
-+ if (free < 0)
-+ goto cleanup;
-+
-+ /* Here we know that we can set the new attribute. */
-+
-+ if (header) {
-+ if (header->h_refcount == cpu_to_le32(1)) {
-+ ea_bdebug(bh, "modifying in-place");
-+ ext2_xattr_cache_remove(bh);
-+ } else {
-+ int offset;
-+
-+ ea_bdebug(bh, "cloning");
-+ header = kmalloc(bh->b_size, GFP_KERNEL);
-+ error = -ENOMEM;
-+ if (header == NULL)
-+ goto cleanup;
-+ memcpy(header, HDR(bh), bh->b_size);
-+ header->h_refcount = cpu_to_le32(1);
-+ offset = (char *)header - bh->b_data;
-+ here = ENTRY((char *)here + offset);
-+ last = ENTRY((char *)last + offset);
-+ }
-+ } else {
-+ /* Allocate a buffer where we construct the new block. */
-+ header = kmalloc(sb->s_blocksize, GFP_KERNEL);
-+ error = -ENOMEM;
-+ if (header == NULL)
-+ goto cleanup;
-+ memset(header, 0, sb->s_blocksize);
-+ end = (char *)header + sb->s_blocksize;
-+ header->h_magic = cpu_to_le32(EXT2_XATTR_MAGIC);
-+ header->h_blocks = header->h_refcount = cpu_to_le32(1);
-+ last = here = ENTRY(header+1);
-+ }
-+
-+ if (not_found) {
-+ /* Insert the new name. */
-+ int size = EXT2_XATTR_LEN(name_len);
-+ int rest = (char *)last - (char *)here;
-+ memmove((char *)here + size, here, rest);
-+ memset(here, 0, size);
-+ here->e_name_index = name_index;
-+ here->e_name_len = name_len;
-+ memcpy(here->e_name, name, name_len);
-+ } else {
-+ /* Remove the old value. */
-+ if (!here->e_value_block && here->e_value_size) {
-+ char *first_val = (char *)header + min_offs;
-+ int offs = le16_to_cpu(here->e_value_offs);
-+ char *val = (char *)header + offs;
-+ size_t size = EXT2_XATTR_SIZE(
-+ le32_to_cpu(here->e_value_size));
-+ memmove(first_val + size, first_val, val - first_val);
-+ memset(first_val, 0, size);
-+ here->e_value_offs = 0;
-+ min_offs += size;
-+
-+ /* Adjust all value offsets. */
-+ last = ENTRY(header+1);
-+ while (!IS_LAST_ENTRY(last)) {
-+ int o = le16_to_cpu(last->e_value_offs);
-+ if (!last->e_value_block && o < offs)
-+ last->e_value_offs =
-+ cpu_to_le16(o + size);
-+ last = EXT2_XATTR_NEXT(last);
-+ }
-+ }
-+ if (value == NULL) {
-+ /* Remove this attribute. */
-+ if (EXT2_XATTR_NEXT(ENTRY(header+1)) == last) {
-+ /* This block is now empty. */
-+ error = ext2_xattr_set2(inode, bh, NULL);
-+ goto cleanup;
-+ } else {
-+ /* Remove the old name. */
-+ int size = EXT2_XATTR_LEN(name_len);
-+ last = ENTRY((char *)last - size);
-+ memmove(here, (char*)here + size,
-+ (char*)last - (char*)here);
-+ memset(last, 0, size);
-+ }
-+ }
-+ }
-+
-+ if (value != NULL) {
-+ /* Insert the new value. */
-+ here->e_value_size = cpu_to_le32(value_len);
-+ if (value_len) {
-+ size_t size = EXT2_XATTR_SIZE(value_len);
-+ char *val = (char *)header + min_offs - size;
-+ here->e_value_offs =
-+ cpu_to_le16((char *)val - (char *)header);
-+ memset(val + size - EXT2_XATTR_PAD, 0,
-+ EXT2_XATTR_PAD); /* Clear the pad bytes. */
-+ memcpy(val, value, value_len);
-+ }
-+ }
-+ ext2_xattr_rehash(header, here);
-+
-+ error = ext2_xattr_set2(inode, bh, header);
-+
-+cleanup:
-+ brelse(bh);
-+ if (!(bh && header == HDR(bh)))
-+ kfree(header);
-+ up(&ext2_xattr_sem);
-+
-+ return error;
-+}
-+
-+/*
-+ * Second half of ext2_xattr_set(): Update the file system.
-+ */
-+static int
-+ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
-+ struct ext2_xattr_header *header)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct buffer_head *new_bh = NULL;
-+ int error;
-+
-+ if (header) {
-+ new_bh = ext2_xattr_cache_find(inode, header);
-+ if (new_bh) {
-+ /*
-+ * We found an identical block in the cache.
-+ * The old block will be released after updating
-+ * the inode.
-+ */
-+ ea_bdebug(old_bh, "reusing block %ld",
-+ new_bh->b_blocknr);
-+
-+ error = -EDQUOT;
-+ if (ext2_xattr_quota_alloc(inode, 1))
-+ goto cleanup;
-+
-+ HDR(new_bh)->h_refcount = cpu_to_le32(
-+ le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
-+ ea_bdebug(new_bh, "refcount now=%d",
-+ le32_to_cpu(HDR(new_bh)->h_refcount));
-+ } else if (old_bh && header == HDR(old_bh)) {
-+ /* Keep this block. */
-+ new_bh = old_bh;
-+ (void)ext2_xattr_cache_insert(new_bh);
-+ } else {
-+ /* We need to allocate a new block */
-+ int force = EXT2_I(inode)->i_file_acl != 0;
-+ int block = ext2_xattr_new_block(inode, &error, force);
-+ if (error)
-+ goto cleanup;
-+ ea_idebug(inode, "creating block %d", block);
-+
-+ new_bh = sb_getblk(sb, block);
-+ if (!new_bh) {
-+ ext2_xattr_free_block(inode, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ lock_buffer(new_bh);
-+ memcpy(new_bh->b_data, header, new_bh->b_size);
-+ mark_buffer_uptodate(new_bh, 1);
-+ unlock_buffer(new_bh);
-+ (void)ext2_xattr_cache_insert(new_bh);
-+
-+ ext2_xattr_update_super_block(sb);
-+ }
-+ mark_buffer_dirty(new_bh);
-+ if (IS_SYNC(inode)) {
-+ ll_rw_block(WRITE, 1, &new_bh);
-+ wait_on_buffer(new_bh);
-+ error = -EIO;
-+ if (buffer_req(new_bh) && !buffer_uptodate(new_bh))
-+ goto cleanup;
-+ }
-+ }
-+
-+ /* Update the inode. */
-+ EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
-+ inode->i_ctime = CURRENT_TIME;
-+ if (IS_SYNC(inode)) {
-+ error = ext2_sync_inode (inode);
-+ if (error)
-+ goto cleanup;
-+ } else
-+ mark_inode_dirty(inode);
-+
-+ error = 0;
-+ if (old_bh && old_bh != new_bh) {
-+ /*
-+ * If there was an old block, and we are not still using it,
-+ * we now release the old block.
-+ */
-+ unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
-+
-+ if (refcount == 1) {
-+ /* Free the old block. */
-+ ea_bdebug(old_bh, "freeing");
-+ ext2_xattr_free_block(inode, old_bh->b_blocknr);
-+ mark_buffer_clean(old_bh);
-+ } else {
-+ /* Decrement the refcount only. */
-+ refcount--;
-+ HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
-+ ext2_xattr_quota_free(inode);
-+ mark_buffer_dirty(old_bh);
-+ ea_bdebug(old_bh, "refcount now=%d", refcount);
-+ }
-+ }
-+
-+cleanup:
-+ if (old_bh != new_bh)
-+ brelse(new_bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * ext2_xattr_delete_inode()
-+ *
-+ * Free extended attribute resources associated with this inode. This
-+ * is called immediately before an inode is freed.
-+ */
-+void
-+ext2_xattr_delete_inode(struct inode *inode)
-+{
-+ struct buffer_head *bh;
-+ unsigned int block = EXT2_I(inode)->i_file_acl;
-+
-+ if (!block)
-+ return;
-+ down(&ext2_xattr_sem);
-+
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh) {
-+ ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
-+ "inode %ld: block %d read error", inode->i_ino, block);
-+ goto cleanup;
-+ }
-+ ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+ ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ goto cleanup;
-+ }
-+ ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
-+ if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
-+ ext2_xattr_cache_remove(bh);
-+ ext2_xattr_free_block(inode, block);
-+ bforget(bh);
-+ bh = NULL;
-+ } else {
-+ HDR(bh)->h_refcount = cpu_to_le32(
-+ le32_to_cpu(HDR(bh)->h_refcount) - 1);
-+ mark_buffer_dirty(bh);
-+ if (IS_SYNC(inode)) {
-+ ll_rw_block(WRITE, 1, &bh);
-+ wait_on_buffer(bh);
-+ }
-+ ext2_xattr_quota_free(inode);
-+ }
-+ EXT2_I(inode)->i_file_acl = 0;
-+
-+cleanup:
-+ brelse(bh);
-+ up(&ext2_xattr_sem);
-+}
-+
-+/*
-+ * ext2_xattr_put_super()
-+ *
-+ * This is called when a file system is unmounted.
-+ */
-+void
-+ext2_xattr_put_super(struct super_block *sb)
-+{
-+#ifdef CONFIG_EXT2_FS_XATTR_SHARING
-+ mb_cache_shrink(ext2_xattr_cache, sb->s_dev);
-+#endif
-+}
-+
-+#ifdef CONFIG_EXT2_FS_XATTR_SHARING
-+
-+/*
-+ * ext2_xattr_cache_insert()
-+ *
-+ * Create a new entry in the extended attribute cache, and insert
-+ * it unless such an entry is already in the cache.
-+ *
-+ * Returns 0, or a negative error number on failure.
-+ */
-+static int
-+ext2_xattr_cache_insert(struct buffer_head *bh)
-+{
-+ __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
-+ struct mb_cache_entry *ce;
-+ int error;
-+
-+ ce = mb_cache_entry_alloc(ext2_xattr_cache);
-+ if (!ce)
-+ return -ENOMEM;
-+ error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
-+ if (error) {
-+ mb_cache_entry_free(ce);
-+ if (error == -EBUSY) {
-+ ea_bdebug(bh, "already in cache (%d cache entries)",
-+ atomic_read(&ext2_xattr_cache->c_entry_count));
-+ error = 0;
-+ }
-+ } else {
-+ ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
-+ atomic_read(&ext2_xattr_cache->c_entry_count));
-+ mb_cache_entry_release(ce);
-+ }
-+ return error;
-+}
-+
-+/*
-+ * ext2_xattr_cmp()
-+ *
-+ * Compare two extended attribute blocks for equality.
-+ *
-+ * Returns 0 if the blocks are equal, 1 if they differ, and
-+ * a negative error number on errors.
-+ */
-+static int
-+ext2_xattr_cmp(struct ext2_xattr_header *header1,
-+ struct ext2_xattr_header *header2)
-+{
-+ struct ext2_xattr_entry *entry1, *entry2;
-+
-+ entry1 = ENTRY(header1+1);
-+ entry2 = ENTRY(header2+1);
-+ while (!IS_LAST_ENTRY(entry1)) {
-+ if (IS_LAST_ENTRY(entry2))
-+ return 1;
-+ if (entry1->e_hash != entry2->e_hash ||
-+ entry1->e_name_len != entry2->e_name_len ||
-+ entry1->e_value_size != entry2->e_value_size ||
-+ memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
-+ return 1;
-+ if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
-+ return -EIO;
-+ if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
-+ (char *)header2 + le16_to_cpu(entry2->e_value_offs),
-+ le32_to_cpu(entry1->e_value_size)))
-+ return 1;
-+
-+ entry1 = EXT2_XATTR_NEXT(entry1);
-+ entry2 = EXT2_XATTR_NEXT(entry2);
-+ }
-+ if (!IS_LAST_ENTRY(entry2))
-+ return 1;
-+ return 0;
-+}
-+
-+/*
-+ * ext2_xattr_cache_find()
-+ *
-+ * Find an identical extended attribute block.
-+ *
-+ * Returns a pointer to the block found, or NULL if such a block was
-+ * not found or an error occurred.
-+ */
-+static struct buffer_head *
-+ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header)
-+{
-+ __u32 hash = le32_to_cpu(header->h_hash);
-+ struct mb_cache_entry *ce;
-+
-+ if (!header->h_hash)
-+ return NULL; /* never share */
-+ ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
-+ ce = mb_cache_entry_find_first(ext2_xattr_cache, 0, inode->i_dev, hash);
-+ while (ce) {
-+ struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
-+
-+ if (!bh) {
-+ ext2_error(inode->i_sb, "ext2_xattr_cache_find",
-+ "inode %ld: block %ld read error",
-+ inode->i_ino, ce->e_block);
-+ } else if (le32_to_cpu(HDR(bh)->h_refcount) >
-+ EXT2_XATTR_REFCOUNT_MAX) {
-+ ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
-+ le32_to_cpu(HDR(bh)->h_refcount),
-+ EXT2_XATTR_REFCOUNT_MAX);
-+ } else if (!ext2_xattr_cmp(header, HDR(bh))) {
-+ ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
-+ mb_cache_entry_release(ce);
-+ return bh;
-+ }
-+ brelse(bh);
-+ ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
-+ }
-+ return NULL;
-+}
-+
-+/*
-+ * ext2_xattr_cache_remove()
-+ *
-+ * Remove the cache entry of a block from the cache. Called when a
-+ * block becomes invalid.
-+ */
-+static void
-+ext2_xattr_cache_remove(struct buffer_head *bh)
-+{
-+ struct mb_cache_entry *ce;
-+
-+ ce = mb_cache_entry_get(ext2_xattr_cache, bh->b_dev, bh->b_blocknr);
-+ if (ce) {
-+ ea_bdebug(bh, "removing (%d cache entries remaining)",
-+ atomic_read(&ext2_xattr_cache->c_entry_count)-1);
-+ mb_cache_entry_free(ce);
-+ } else
-+ ea_bdebug(bh, "no cache entry");
-+}
-+
-+#define NAME_HASH_SHIFT 5
-+#define VALUE_HASH_SHIFT 16
-+
-+/*
-+ * ext2_xattr_hash_entry()
-+ *
-+ * Compute the hash of an extended attribute.
-+ */
-+static inline void ext2_xattr_hash_entry(struct ext2_xattr_header *header,
-+ struct ext2_xattr_entry *entry)
-+{
-+ __u32 hash = 0;
-+ char *name = entry->e_name;
-+ int n;
-+
-+ for (n=0; n < entry->e_name_len; n++) {
-+ hash = (hash << NAME_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
-+ *name++;
-+ }
-+
-+ if (entry->e_value_block == 0 && entry->e_value_size != 0) {
-+ __u32 *value = (__u32 *)((char *)header +
-+ le16_to_cpu(entry->e_value_offs));
-+ for (n = (le32_to_cpu(entry->e_value_size) +
-+ EXT2_XATTR_ROUND) >> EXT2_XATTR_PAD_BITS; n; n--) {
-+ hash = (hash << VALUE_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
-+ le32_to_cpu(*value++);
-+ }
-+ }
-+ entry->e_hash = cpu_to_le32(hash);
-+}
-+
-+#undef NAME_HASH_SHIFT
-+#undef VALUE_HASH_SHIFT
-+
-+#define BLOCK_HASH_SHIFT 16
-+
-+/*
-+ * ext2_xattr_rehash()
-+ *
-+ * Re-compute the extended attribute hash value after an entry has changed.
-+ */
-+static void ext2_xattr_rehash(struct ext2_xattr_header *header,
-+ struct ext2_xattr_entry *entry)
-+{
-+ struct ext2_xattr_entry *here;
-+ __u32 hash = 0;
-+
-+ ext2_xattr_hash_entry(header, entry);
-+ here = ENTRY(header+1);
-+ while (!IS_LAST_ENTRY(here)) {
-+ if (!here->e_hash) {
-+ /* Block is not shared if an entry's hash value == 0 */
-+ hash = 0;
-+ break;
-+ }
-+ hash = (hash << BLOCK_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
-+ le32_to_cpu(here->e_hash);
-+ here = EXT2_XATTR_NEXT(here);
-+ }
-+ header->h_hash = cpu_to_le32(hash);
-+}
-+
-+#undef BLOCK_HASH_SHIFT
-+
-+int __init
-+init_ext2_xattr(void)
-+{
-+ ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL,
-+ sizeof(struct mb_cache_entry) +
-+ sizeof(struct mb_cache_entry_index), 1, 61);
-+ if (!ext2_xattr_cache)
-+ return -ENOMEM;
-+
-+ return 0;
-+}
-+
-+void
-+exit_ext2_xattr(void)
-+{
-+ mb_cache_destroy(ext2_xattr_cache);
-+}
-+
-+#else /* CONFIG_EXT2_FS_XATTR_SHARING */
-+
-+int __init
-+init_ext2_xattr(void)
-+{
-+ return 0;
-+}
-+
-+void
-+exit_ext2_xattr(void)
-+{
-+}
-+
-+#endif /* CONFIG_EXT2_FS_XATTR_SHARING */
-Index: linux-2.4.24-vanilla/fs/ext2/xattr_user.c
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/ext2/xattr_user.c 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.24-vanilla/fs/ext2/xattr_user.c 2004-01-10 17:20:28.000000000 +0300
-@@ -0,0 +1,103 @@
-+/*
-+ * linux/fs/ext2/xattr_user.c
-+ * Handler for extended user attributes.
-+ *
-+ * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/string.h>
-+#include <linux/fs.h>
-+#include <linux/ext2_fs.h>
-+#include <linux/ext2_xattr.h>
-+
-+#ifdef CONFIG_EXT2_FS_POSIX_ACL
-+# include <linux/ext2_acl.h>
-+#endif
-+
-+#define XATTR_USER_PREFIX "user."
-+
-+static size_t
-+ext2_xattr_user_list(char *list, struct inode *inode,
-+ const char *name, int name_len)
-+{
-+ const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
-+
-+ if (!test_opt(inode->i_sb, XATTR_USER))
-+ return 0;
-+
-+ if (list) {
-+ memcpy(list, XATTR_USER_PREFIX, prefix_len);
-+ memcpy(list+prefix_len, name, name_len);
-+ list[prefix_len + name_len] = '\0';
-+ }
-+ return prefix_len + name_len + 1;
-+}
-+
-+static int
-+ext2_xattr_user_get(struct inode *inode, const char *name,
-+ void *buffer, size_t size)
-+{
-+ int error;
-+
-+ if (strcmp(name, "") == 0)
-+ return -EINVAL;
-+ if (!test_opt(inode->i_sb, XATTR_USER))
-+ return -ENOTSUP;
-+#ifdef CONFIG_EXT2_FS_POSIX_ACL
-+ error = ext2_permission_locked(inode, MAY_READ);
-+#else
-+ error = permission(inode, MAY_READ);
-+#endif
-+ if (error)
-+ return error;
-+
-+ return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name,
-+ buffer, size);
-+}
-+
-+static int
-+ext2_xattr_user_set(struct inode *inode, const char *name,
-+ const void *value, size_t size, int flags)
-+{
-+ int error;
-+
-+ if (strcmp(name, "") == 0)
-+ return -EINVAL;
-+ if (!test_opt(inode->i_sb, XATTR_USER))
-+ return -ENOTSUP;
-+ if ( !S_ISREG(inode->i_mode) &&
-+ (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
-+ return -EPERM;
-+#ifdef CONFIG_EXT2_FS_POSIX_ACL
-+ error = ext2_permission_locked(inode, MAY_WRITE);
-+#else
-+ error = permission(inode, MAY_WRITE);
-+#endif
-+ if (error)
-+ return error;
-+
-+ return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name,
-+ value, size, flags);
-+}
-+
-+struct ext2_xattr_handler ext2_xattr_user_handler = {
-+ prefix: XATTR_USER_PREFIX,
-+ list: ext2_xattr_user_list,
-+ get: ext2_xattr_user_get,
-+ set: ext2_xattr_user_set,
-+};
-+
-+int __init
-+init_ext2_xattr_user(void)
-+{
-+ return ext2_xattr_register(EXT2_XATTR_INDEX_USER,
-+ &ext2_xattr_user_handler);
-+}
-+
-+void
-+exit_ext2_xattr_user(void)
-+{
-+ ext2_xattr_unregister(EXT2_XATTR_INDEX_USER,
-+ &ext2_xattr_user_handler);
-+}
-Index: linux-2.4.24-vanilla/fs/ext3/Makefile
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/ext3/Makefile 2004-01-10 17:11:50.000000000 +0300
-+++ linux-2.4.24-vanilla/fs/ext3/Makefile 2004-01-10 17:20:28.000000000 +0300
-@@ -1,5 +1,5 @@
- #
--# Makefile for the linux ext2-filesystem routines.
-+# Makefile for the linux ext3-filesystem routines.
- #
- # Note! Dependencies are done automagically by 'make dep', which also
- # removes any old dependencies. DON'T put your own dependencies here
-@@ -9,10 +9,14 @@
-
- O_TARGET := ext3.o
-
--export-objs := super.o inode.o
-+export-objs := ext3-exports.o
-
- obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
-- ioctl.o namei.o super.o symlink.o hash.o
-+ ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o
- obj-m := $(O_TARGET)
-
-+export-objs += xattr.o
-+obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o
-+obj-$(CONFIG_EXT3_FS_XATTR_USER) += xattr_user.o
-+
- include $(TOPDIR)/Rules.make
-Index: linux-2.4.24-vanilla/fs/ext3/file.c
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/ext3/file.c 2004-01-10 17:11:50.000000000 +0300
-+++ linux-2.4.24-vanilla/fs/ext3/file.c 2004-01-10 17:20:28.000000000 +0300
-@@ -23,6 +23,7 @@
- #include <linux/locks.h>
- #include <linux/jbd.h>
- #include <linux/ext3_fs.h>
-+#include <linux/ext3_xattr.h>
- #include <linux/ext3_jbd.h>
- #include <linux/smp_lock.h>
-
-@@ -127,5 +128,9 @@
- struct inode_operations ext3_file_inode_operations = {
- truncate: ext3_truncate, /* BKL held */
- setattr: ext3_setattr, /* BKL held */
-+ setxattr: ext3_setxattr, /* BKL held */
-+ getxattr: ext3_getxattr, /* BKL held */
-+ listxattr: ext3_listxattr, /* BKL held */
-+ removexattr: ext3_removexattr, /* BKL held */
- };
-
-Index: linux-2.4.24-vanilla/fs/ext3/ialloc.c
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/ext3/ialloc.c 2004-01-10 17:04:42.000000000 +0300
-+++ linux-2.4.24-vanilla/fs/ext3/ialloc.c 2004-01-10 17:20:28.000000000 +0300
-@@ -17,6 +17,7 @@
- #include <linux/jbd.h>
- #include <linux/ext3_fs.h>
- #include <linux/ext3_jbd.h>
-+#include <linux/ext3_xattr.h>
- #include <linux/stat.h>
- #include <linux/string.h>
- #include <linux/locks.h>
-@@ -216,6 +217,7 @@
- * as writing the quota to disk may need the lock as well.
- */
- DQUOT_INIT(inode);
-+ ext3_xattr_delete_inode(handle, inode);
- DQUOT_FREE_INODE(inode);
- DQUOT_DROP(inode);
-
-Index: linux-2.4.24-vanilla/fs/ext3/inode.c
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/ext3/inode.c 2004-01-10 17:05:05.000000000 +0300
-+++ linux-2.4.24-vanilla/fs/ext3/inode.c 2004-01-10 17:20:28.000000000 +0300
-@@ -39,6 +39,18 @@
- */
- #undef SEARCH_FROM_ZERO
-
-+/*
-+ * Test whether an inode is a fast symlink.
-+ */
-+static inline int ext3_inode_is_fast_symlink(struct inode *inode)
-+{
-+ int ea_blocks = inode->u.ext3_i.i_file_acl ?
-+ (inode->i_sb->s_blocksize >> 9) : 0;
-+
-+ return (S_ISLNK(inode->i_mode) &&
-+ inode->i_blocks - ea_blocks == 0);
-+}
-+
- /* The ext3 forget function must perform a revoke if we are freeing data
- * which has been journaled. Metadata (eg. indirect blocks) must be
- * revoked in all cases.
-@@ -48,7 +60,7 @@
- * still needs to be revoked.
- */
-
--static int ext3_forget(handle_t *handle, int is_metadata,
-+int ext3_forget(handle_t *handle, int is_metadata,
- struct inode *inode, struct buffer_head *bh,
- int blocknr)
- {
-@@ -179,9 +191,7 @@
- {
- handle_t *handle;
-
-- if (is_bad_inode(inode) ||
-- inode->i_ino == EXT3_ACL_IDX_INO ||
-- inode->i_ino == EXT3_ACL_DATA_INO)
-+ if (is_bad_inode(inode))
- goto no_delete;
-
- lock_kernel();
-@@ -1870,6 +1880,8 @@
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return;
-+ if (ext3_inode_is_fast_symlink(inode))
-+ return;
- if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
- return;
-
-@@ -2017,8 +2029,6 @@
- struct ext3_group_desc * gdp;
-
- if ((inode->i_ino != EXT3_ROOT_INO &&
-- inode->i_ino != EXT3_ACL_IDX_INO &&
-- inode->i_ino != EXT3_ACL_DATA_INO &&
- inode->i_ino != EXT3_JOURNAL_INO &&
- inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
- inode->i_ino > le32_to_cpu(
-@@ -2159,10 +2169,7 @@
- inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block];
- INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
-
-- if (inode->i_ino == EXT3_ACL_IDX_INO ||
-- inode->i_ino == EXT3_ACL_DATA_INO)
-- /* Nothing to do */ ;
-- else if (S_ISREG(inode->i_mode)) {
-+ if (S_ISREG(inode->i_mode)) {
- inode->i_op = &ext3_file_inode_operations;
- inode->i_fop = &ext3_file_operations;
- inode->i_mapping->a_ops = &ext3_aops;
-@@ -2170,15 +2177,17 @@
- inode->i_op = &ext3_dir_inode_operations;
- inode->i_fop = &ext3_dir_operations;
- } else if (S_ISLNK(inode->i_mode)) {
-- if (!inode->i_blocks)
-+ if (ext3_inode_is_fast_symlink(inode))
- inode->i_op = &ext3_fast_symlink_inode_operations;
- else {
-- inode->i_op = &page_symlink_inode_operations;
-+ inode->i_op = &ext3_symlink_inode_operations;
- inode->i_mapping->a_ops = &ext3_aops;
- }
-- } else
-+ } else {
-+ inode->i_op = &ext3_special_inode_operations;
- init_special_inode(inode, inode->i_mode,
- le32_to_cpu(iloc.raw_inode->i_block[0]));
-+ }
- brelse(iloc.bh);
- ext3_set_inode_flags(inode);
- return;
-Index: linux-2.4.24-vanilla/fs/ext3/namei.c
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/ext3/namei.c 2004-01-10 17:11:50.000000000 +0300
-+++ linux-2.4.24-vanilla/fs/ext3/namei.c 2004-01-10 17:20:28.000000000 +0300
-@@ -29,6 +29,7 @@
- #include <linux/sched.h>
- #include <linux/ext3_fs.h>
- #include <linux/ext3_jbd.h>
-+#include <linux/ext3_xattr.h>
- #include <linux/fcntl.h>
- #include <linux/stat.h>
- #include <linux/string.h>
-@@ -1613,7 +1614,7 @@
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-
-- inode = ext3_new_inode (handle, dir, S_IFDIR);
-+ inode = ext3_new_inode (handle, dir, S_IFDIR | mode);
- err = PTR_ERR(inode);
- if (IS_ERR(inode))
- goto out_stop;
-@@ -1621,7 +1622,6 @@
- inode->i_op = &ext3_dir_inode_operations;
- inode->i_fop = &ext3_dir_operations;
- inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
-- inode->i_blocks = 0;
- dir_block = ext3_bread (handle, inode, 0, 1, &err);
- if (!dir_block) {
- inode->i_nlink--; /* is this nlink == 0? */
-@@ -1648,9 +1648,6 @@
- BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata");
- ext3_journal_dirty_metadata(handle, dir_block);
- brelse (dir_block);
-- inode->i_mode = S_IFDIR | mode;
-- if (dir->i_mode & S_ISGID)
-- inode->i_mode |= S_ISGID;
- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_entry (handle, dentry, inode);
- if (err) {
-@@ -2019,7 +2016,7 @@
- goto out_stop;
-
- if (l > sizeof (EXT3_I(inode)->i_data)) {
-- inode->i_op = &page_symlink_inode_operations;
-+ inode->i_op = &ext3_symlink_inode_operations;
- inode->i_mapping->a_ops = &ext3_aops;
- /*
- * block_symlink() calls back into ext3_prepare/commit_write.
-@@ -2244,4 +2241,16 @@
- rmdir: ext3_rmdir, /* BKL held */
- mknod: ext3_mknod, /* BKL held */
- rename: ext3_rename, /* BKL held */
-+ setxattr: ext3_setxattr, /* BKL held */
-+ getxattr: ext3_getxattr, /* BKL held */
-+ listxattr: ext3_listxattr, /* BKL held */
-+ removexattr: ext3_removexattr, /* BKL held */
- };
-+
-+struct inode_operations ext3_special_inode_operations = {
-+ setxattr: ext3_setxattr, /* BKL held */
-+ getxattr: ext3_getxattr, /* BKL held */
-+ listxattr: ext3_listxattr, /* BKL held */
-+ removexattr: ext3_removexattr, /* BKL held */
-+};
-+
-Index: linux-2.4.24-vanilla/fs/ext3/super.c
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/ext3/super.c 2004-01-10 17:11:50.000000000 +0300
-+++ linux-2.4.24-vanilla/fs/ext3/super.c 2004-01-10 17:20:28.000000000 +0300
-@@ -24,6 +24,7 @@
- #include <linux/jbd.h>
- #include <linux/ext3_fs.h>
- #include <linux/ext3_jbd.h>
-+#include <linux/ext3_xattr.h>
- #include <linux/slab.h>
- #include <linux/init.h>
- #include <linux/locks.h>
-@@ -406,6 +407,7 @@
- kdev_t j_dev = sbi->s_journal->j_dev;
- int i;
-
-+ ext3_xattr_put_super(sb);
- journal_destroy(sbi->s_journal);
- if (!(sb->s_flags & MS_RDONLY)) {
- EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
-@@ -505,6 +507,7 @@
- int is_remount)
- {
- unsigned long *mount_options = &sbi->s_mount_opt;
-+
- uid_t *resuid = &sbi->s_resuid;
- gid_t *resgid = &sbi->s_resgid;
- char * this_char;
-@@ -517,6 +520,13 @@
- this_char = strtok (NULL, ",")) {
- if ((value = strchr (this_char, '=')) != NULL)
- *value++ = 0;
-+#ifdef CONFIG_EXT3_FS_XATTR_USER
-+ if (!strcmp (this_char, "user_xattr"))
-+ set_opt (*mount_options, XATTR_USER);
-+ else if (!strcmp (this_char, "nouser_xattr"))
-+ clear_opt (*mount_options, XATTR_USER);
-+ else
-+#endif
- if (!strcmp (this_char, "bsddf"))
- clear_opt (*mount_options, MINIX_DF);
- else if (!strcmp (this_char, "nouid32")) {
-@@ -934,6 +944,12 @@
- sbi->s_mount_opt = 0;
- sbi->s_resuid = EXT3_DEF_RESUID;
- sbi->s_resgid = EXT3_DEF_RESGID;
-+
-+ /* Default extended attribute flags */
-+#ifdef CONFIG_EXT3_FS_XATTR_USER
-+ /* set_opt(sbi->s_mount_opt, XATTR_USER); */
-+#endif
-+
- if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0)) {
- sb->s_dev = 0;
- goto out_fail;
-@@ -1822,22 +1838,35 @@
-
- static int __init init_ext3_fs(void)
- {
-+ int error;
- #ifdef CONFIG_QUOTA
- init_dquot_operations(&ext3_qops);
- old_sync_dquot = ext3_qops.sync_dquot;
- ext3_qops.sync_dquot = ext3_sync_dquot;
- #endif
-- return register_filesystem(&ext3_fs_type);
-+ error = init_ext3_xattr();
-+ if (error)
-+ return error;
-+ error = init_ext3_xattr_user();
-+ if (error)
-+ goto fail;
-+ error = register_filesystem(&ext3_fs_type);
-+ if (!error)
-+ return 0;
-+
-+ exit_ext3_xattr_user();
-+fail:
-+ exit_ext3_xattr();
-+ return error;
- }
-
- static void __exit exit_ext3_fs(void)
- {
- unregister_filesystem(&ext3_fs_type);
-+ exit_ext3_xattr_user();
-+ exit_ext3_xattr();
- }
-
--EXPORT_SYMBOL(ext3_force_commit);
--EXPORT_SYMBOL(ext3_bread);
--
- MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
- MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
- MODULE_LICENSE("GPL");
-Index: linux-2.4.24-vanilla/fs/ext3/symlink.c
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/ext3/symlink.c 2001-11-10 01:25:04.000000000 +0300
-+++ linux-2.4.24-vanilla/fs/ext3/symlink.c 2004-01-10 17:20:28.000000000 +0300
-@@ -20,6 +20,7 @@
- #include <linux/fs.h>
- #include <linux/jbd.h>
- #include <linux/ext3_fs.h>
-+#include <linux/ext3_xattr.h>
-
- static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen)
- {
-@@ -33,7 +34,20 @@
- return vfs_follow_link(nd, s);
- }
-
-+struct inode_operations ext3_symlink_inode_operations = {
-+ readlink: page_readlink, /* BKL not held. Don't need */
-+ follow_link: page_follow_link, /* BKL not held. Don't need */
-+ setxattr: ext3_setxattr, /* BKL held */
-+ getxattr: ext3_getxattr, /* BKL held */
-+ listxattr: ext3_listxattr, /* BKL held */
-+ removexattr: ext3_removexattr, /* BKL held */
-+};
-+
- struct inode_operations ext3_fast_symlink_inode_operations = {
- readlink: ext3_readlink, /* BKL not held. Don't need */
- follow_link: ext3_follow_link, /* BKL not held. Don't need */
-+ setxattr: ext3_setxattr, /* BKL held */
-+ getxattr: ext3_getxattr, /* BKL held */
-+ listxattr: ext3_listxattr, /* BKL held */
-+ removexattr: ext3_removexattr, /* BKL held */
- };
-Index: linux-2.4.24-vanilla/fs/ext3/xattr.c
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/ext3/xattr.c 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.24-vanilla/fs/ext3/xattr.c 2004-01-10 17:20:28.000000000 +0300
-@@ -0,0 +1,1225 @@
-+/*
-+ * linux/fs/ext3/xattr.c
-+ *
-+ * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ *
-+ * Fix by Harrison Xing <harrison@mountainviewdata.com>.
-+ * Ext3 code with a lot of help from Eric Jarman <ejarman@acm.org>.
-+ * Extended attributes for symlinks and special files added per
-+ * suggestion of Luka Renko <luka.renko@hermes.si>.
-+ */
-+
-+/*
-+ * Extended attributes are stored on disk blocks allocated outside of
-+ * any inode. The i_file_acl field is then made to point to this allocated
-+ * block. If all extended attributes of an inode are identical, these
-+ * inodes may share the same extended attribute block. Such situations
-+ * are automatically detected by keeping a cache of recent attribute block
-+ * numbers and hashes over the block's contents in memory.
-+ *
-+ *
-+ * Extended attribute block layout:
-+ *
-+ * +------------------+
-+ * | header |
-+ * | entry 1 | |
-+ * | entry 2 | | growing downwards
-+ * | entry 3 | v
-+ * | four null bytes |
-+ * | . . . |
-+ * | value 1 | ^
-+ * | value 3 | | growing upwards
-+ * | value 2 | |
-+ * +------------------+
-+ *
-+ * The block header is followed by multiple entry descriptors. These entry
-+ * descriptors are variable in size, and alligned to EXT3_XATTR_PAD
-+ * byte boundaries. The entry descriptors are sorted by attribute name,
-+ * so that two extended attribute blocks can be compared efficiently.
-+ *
-+ * Attribute values are aligned to the end of the block, stored in
-+ * no specific order. They are also padded to EXT3_XATTR_PAD byte
-+ * boundaries. No additional gaps are left between them.
-+ *
-+ * Locking strategy
-+ * ----------------
-+ * The VFS already holds the BKL and the inode->i_sem semaphore when any of
-+ * the xattr inode operations are called, so we are guaranteed that only one
-+ * processes accesses extended attributes of an inode at any time.
-+ *
-+ * For writing we also grab the ext3_xattr_sem semaphore. This ensures that
-+ * only a single process is modifying an extended attribute block, even
-+ * if the block is shared among inodes.
-+ *
-+ * Note for porting to 2.5
-+ * -----------------------
-+ * The BKL will no longer be held in the xattr inode operations.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/fs.h>
-+#include <linux/locks.h>
-+#include <linux/slab.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/ext3_fs.h>
-+#include <linux/ext3_xattr.h>
-+#include <linux/mbcache.h>
-+#include <linux/quotaops.h>
-+#include <asm/semaphore.h>
-+#include <linux/compatmac.h>
-+
-+#define EXT3_EA_USER "user."
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-+# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
-+#endif
-+
-+#define HDR(bh) ((struct ext3_xattr_header *)((bh)->b_data))
-+#define ENTRY(ptr) ((struct ext3_xattr_entry *)(ptr))
-+#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
-+#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
-+
-+#ifdef EXT3_XATTR_DEBUG
-+# define ea_idebug(inode, f...) do { \
-+ printk(KERN_DEBUG "inode %s:%ld: ", \
-+ kdevname(inode->i_dev), inode->i_ino); \
-+ printk(f); \
-+ printk("\n"); \
-+ } while (0)
-+# define ea_bdebug(bh, f...) do { \
-+ printk(KERN_DEBUG "block %s:%ld: ", \
-+ kdevname(bh->b_dev), bh->b_blocknr); \
-+ printk(f); \
-+ printk("\n"); \
-+ } while (0)
-+#else
-+# define ea_idebug(f...)
-+# define ea_bdebug(f...)
-+#endif
-+
-+static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *,
-+ struct ext3_xattr_header *);
-+
-+#ifdef CONFIG_EXT3_FS_XATTR_SHARING
-+
-+static int ext3_xattr_cache_insert(struct buffer_head *);
-+static struct buffer_head *ext3_xattr_cache_find(struct inode *,
-+ struct ext3_xattr_header *);
-+static void ext3_xattr_cache_remove(struct buffer_head *);
-+static void ext3_xattr_rehash(struct ext3_xattr_header *,
-+ struct ext3_xattr_entry *);
-+
-+static struct mb_cache *ext3_xattr_cache;
-+
-+#else
-+# define ext3_xattr_cache_insert(bh) 0
-+# define ext3_xattr_cache_find(inode, header) NULL
-+# define ext3_xattr_cache_remove(bh) while(0) {}
-+# define ext3_xattr_rehash(header, entry) while(0) {}
-+#endif
-+
-+/*
-+ * If a file system does not share extended attributes among inodes,
-+ * we should not need the ext3_xattr_sem semaphore. However, the
-+ * filesystem may still contain shared blocks, so we always take
-+ * the lock.
-+ */
-+
-+DECLARE_MUTEX(ext3_xattr_sem);
-+
-+static inline int
-+ext3_xattr_new_block(handle_t *handle, struct inode *inode,
-+ int * errp, int force)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ int goal = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) +
-+ EXT3_I(inode)->i_block_group * EXT3_BLOCKS_PER_GROUP(sb);
-+
-+ /* How can we enforce the allocation? */
-+ int block = ext3_new_block(handle, inode, goal, 0, 0, errp);
-+#ifdef OLD_QUOTAS
-+ if (!*errp)
-+ inode->i_blocks += inode->i_sb->s_blocksize >> 9;
-+#endif
-+ return block;
-+}
-+
-+static inline int
-+ext3_xattr_quota_alloc(struct inode *inode, int force)
-+{
-+ /* How can we enforce the allocation? */
-+#ifdef OLD_QUOTAS
-+ int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1);
-+ if (!error)
-+ inode->i_blocks += inode->i_sb->s_blocksize >> 9;
-+#else
-+ int error = DQUOT_ALLOC_BLOCK(inode, 1);
-+#endif
-+ return error;
-+}
-+
-+#ifdef OLD_QUOTAS
-+
-+static inline void
-+ext3_xattr_quota_free(struct inode *inode)
-+{
-+ DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
-+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
-+}
-+
-+static inline void
-+ext3_xattr_free_block(handle_t *handle, struct inode * inode,
-+ unsigned long block)
-+{
-+ ext3_free_blocks(handle, inode, block, 1);
-+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
-+}
-+
-+#else
-+# define ext3_xattr_quota_free(inode) \
-+ DQUOT_FREE_BLOCK(inode, 1)
-+# define ext3_xattr_free_block(handle, inode, block) \
-+ ext3_free_blocks(handle, inode, block, 1)
-+#endif
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
-+
-+static inline struct buffer_head *
-+sb_bread(struct super_block *sb, int block)
-+{
-+ return bread(sb->s_dev, block, sb->s_blocksize);
-+}
-+
-+static inline struct buffer_head *
-+sb_getblk(struct super_block *sb, int block)
-+{
-+ return getblk(sb->s_dev, block, sb->s_blocksize);
-+}
-+
-+#endif
-+
-+struct ext3_xattr_handler *ext3_xattr_handlers[EXT3_XATTR_INDEX_MAX];
-+rwlock_t ext3_handler_lock = RW_LOCK_UNLOCKED;
-+
-+int
-+ext3_xattr_register(int name_index, struct ext3_xattr_handler *handler)
-+{
-+ int error = -EINVAL;
-+
-+ if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
-+ write_lock(&ext3_handler_lock);
-+ if (!ext3_xattr_handlers[name_index-1]) {
-+ ext3_xattr_handlers[name_index-1] = handler;
-+ error = 0;
-+ }
-+ write_unlock(&ext3_handler_lock);
-+ }
-+ return error;
-+}
-+
-+void
-+ext3_xattr_unregister(int name_index, struct ext3_xattr_handler *handler)
-+{
-+ if (name_index > 0 || name_index <= EXT3_XATTR_INDEX_MAX) {
-+ write_lock(&ext3_handler_lock);
-+ ext3_xattr_handlers[name_index-1] = NULL;
-+ write_unlock(&ext3_handler_lock);
-+ }
-+}
-+
-+static inline const char *
-+strcmp_prefix(const char *a, const char *a_prefix)
-+{
-+ while (*a_prefix && *a == *a_prefix) {
-+ a++;
-+ a_prefix++;
-+ }
-+ return *a_prefix ? NULL : a;
-+}
-+
-+/*
-+ * Decode the extended attribute name, and translate it into
-+ * the name_index and name suffix.
-+ */
-+static inline struct ext3_xattr_handler *
-+ext3_xattr_resolve_name(const char **name)
-+{
-+ struct ext3_xattr_handler *handler = NULL;
-+ int i;
-+
-+ if (!*name)
-+ return NULL;
-+ read_lock(&ext3_handler_lock);
-+ for (i=0; i<EXT3_XATTR_INDEX_MAX; i++) {
-+ if (ext3_xattr_handlers[i]) {
-+ const char *n = strcmp_prefix(*name,
-+ ext3_xattr_handlers[i]->prefix);
-+ if (n) {
-+ handler = ext3_xattr_handlers[i];
-+ *name = n;
-+ break;
-+ }
-+ }
-+ }
-+ read_unlock(&ext3_handler_lock);
-+ return handler;
-+}
-+
-+static inline struct ext3_xattr_handler *
-+ext3_xattr_handler(int name_index)
-+{
-+ struct ext3_xattr_handler *handler = NULL;
-+ if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
-+ read_lock(&ext3_handler_lock);
-+ handler = ext3_xattr_handlers[name_index-1];
-+ read_unlock(&ext3_handler_lock);
-+ }
-+ return handler;
-+}
-+
-+/*
-+ * Inode operation getxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ * BKL held [before 2.5.x]
-+ */
-+ssize_t
-+ext3_getxattr(struct dentry *dentry, const char *name,
-+ void *buffer, size_t size)
-+{
-+ struct ext3_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ handler = ext3_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -ENOTSUP;
-+ return handler->get(inode, name, buffer, size);
-+}
-+
-+/*
-+ * Inode operation listxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ * BKL held [before 2.5.x]
-+ */
-+ssize_t
-+ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
-+{
-+ return ext3_xattr_list(dentry->d_inode, buffer, size);
-+}
-+
-+/*
-+ * Inode operation setxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ * BKL held [before 2.5.x]
-+ */
-+int
-+ext3_setxattr(struct dentry *dentry, const char *name,
-+ const void *value, size_t size, int flags)
-+{
-+ struct ext3_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ if (size == 0)
-+ value = ""; /* empty EA, do not remove */
-+ handler = ext3_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -ENOTSUP;
-+ return handler->set(inode, name, value, size, flags);
-+}
-+
-+/*
-+ * Inode operation removexattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ * BKL held [before 2.5.x]
-+ */
-+int
-+ext3_removexattr(struct dentry *dentry, const char *name)
-+{
-+ struct ext3_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ handler = ext3_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -ENOTSUP;
-+ return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
-+}
-+
-+/*
-+ * ext3_xattr_get()
-+ *
-+ * Copy an extended attribute into the buffer
-+ * provided, or compute the buffer size required.
-+ * Buffer is NULL to compute the size of the buffer required.
-+ *
-+ * Returns a negative error number on failure, or the number of bytes
-+ * used / required on success.
-+ */
-+int
-+ext3_xattr_get(struct inode *inode, int name_index, const char *name,
-+ void *buffer, size_t buffer_size)
-+{
-+ struct buffer_head *bh = NULL;
-+ struct ext3_xattr_entry *entry;
-+ unsigned int block, size;
-+ char *end;
-+ int name_len, error;
-+
-+ ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
-+ name_index, name, buffer, (long)buffer_size);
-+
-+ if (name == NULL)
-+ return -EINVAL;
-+ if (!EXT3_I(inode)->i_file_acl)
-+ return -ENOATTR;
-+ block = EXT3_I(inode)->i_file_acl;
-+ ea_idebug(inode, "reading block %d", block);
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh)
-+ return -EIO;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
-+ end = bh->b_data + bh->b_size;
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext3_error(inode->i_sb, "ext3_xattr_get",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* find named attribute */
-+ name_len = strlen(name);
-+
-+ error = -ERANGE;
-+ if (name_len > 255)
-+ goto cleanup;
-+ entry = FIRST_ENTRY(bh);
-+ while (!IS_LAST_ENTRY(entry)) {
-+ struct ext3_xattr_entry *next =
-+ EXT3_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (name_index == entry->e_name_index &&
-+ name_len == entry->e_name_len &&
-+ memcmp(name, entry->e_name, name_len) == 0)
-+ goto found;
-+ entry = next;
-+ }
-+ /* Check the remaining name entries */
-+ while (!IS_LAST_ENTRY(entry)) {
-+ struct ext3_xattr_entry *next =
-+ EXT3_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ entry = next;
-+ }
-+ if (ext3_xattr_cache_insert(bh))
-+ ea_idebug(inode, "cache insert failed");
-+ error = -ENOATTR;
-+ goto cleanup;
-+found:
-+ /* check the buffer size */
-+ if (entry->e_value_block != 0)
-+ goto bad_block;
-+ size = le32_to_cpu(entry->e_value_size);
-+ if (size > inode->i_sb->s_blocksize ||
-+ le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
-+ goto bad_block;
-+
-+ if (ext3_xattr_cache_insert(bh))
-+ ea_idebug(inode, "cache insert failed");
-+ if (buffer) {
-+ error = -ERANGE;
-+ if (size > buffer_size)
-+ goto cleanup;
-+ /* return value of attribute */
-+ memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
-+ size);
-+ }
-+ error = size;
-+
-+cleanup:
-+ brelse(bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * ext3_xattr_list()
-+ *
-+ * Copy a list of attribute names into the buffer
-+ * provided, or compute the buffer size required.
-+ * Buffer is NULL to compute the size of the buffer required.
-+ *
-+ * Returns a negative error number on failure, or the number of bytes
-+ * used / required on success.
-+ */
-+int
-+ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
-+{
-+ struct buffer_head *bh = NULL;
-+ struct ext3_xattr_entry *entry;
-+ unsigned int block, size = 0;
-+ char *buf, *end;
-+ int error;
-+
-+ ea_idebug(inode, "buffer=%p, buffer_size=%ld",
-+ buffer, (long)buffer_size);
-+
-+ if (!EXT3_I(inode)->i_file_acl)
-+ return 0;
-+ block = EXT3_I(inode)->i_file_acl;
-+ ea_idebug(inode, "reading block %d", block);
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh)
-+ return -EIO;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
-+ end = bh->b_data + bh->b_size;
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext3_error(inode->i_sb, "ext3_xattr_list",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* compute the size required for the list of attribute names */
-+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
-+ entry = EXT3_XATTR_NEXT(entry)) {
-+ struct ext3_xattr_handler *handler;
-+ struct ext3_xattr_entry *next =
-+ EXT3_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+
-+ handler = ext3_xattr_handler(entry->e_name_index);
-+ if (handler)
-+ size += handler->list(NULL, inode, entry->e_name,
-+ entry->e_name_len);
-+ }
-+
-+ if (ext3_xattr_cache_insert(bh))
-+ ea_idebug(inode, "cache insert failed");
-+ if (!buffer) {
-+ error = size;
-+ goto cleanup;
-+ } else {
-+ error = -ERANGE;
-+ if (size > buffer_size)
-+ goto cleanup;
-+ }
-+
-+ /* list the attribute names */
-+ buf = buffer;
-+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
-+ entry = EXT3_XATTR_NEXT(entry)) {
-+ struct ext3_xattr_handler *handler;
-+
-+ handler = ext3_xattr_handler(entry->e_name_index);
-+ if (handler)
-+ buf += handler->list(buf, inode, entry->e_name,
-+ entry->e_name_len);
-+ }
-+ error = size;
-+
-+cleanup:
-+ brelse(bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
-+ * not set, set it.
-+ */
-+static void ext3_xattr_update_super_block(handle_t *handle,
-+ struct super_block *sb)
-+{
-+ if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR))
-+ return;
-+
-+ lock_super(sb);
-+ ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-+ EXT3_SB(sb)->s_feature_compat |= EXT3_FEATURE_COMPAT_EXT_ATTR;
-+#endif
-+ EXT3_SB(sb)->s_es->s_feature_compat |=
-+ cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR);
-+ sb->s_dirt = 1;
-+ ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
-+ unlock_super(sb);
-+}
-+
-+/*
-+ * ext3_xattr_set()
-+ *
-+ * Create, replace or remove an extended attribute for this inode. Buffer
-+ * is NULL to remove an existing extended attribute, and non-NULL to
-+ * either replace an existing extended attribute, or create a new extended
-+ * attribute. The flags XATTR_REPLACE and XATTR_CREATE
-+ * specify that an extended attribute must exist and must not exist
-+ * previous to the call, respectively.
-+ *
-+ * Returns 0, or a negative error number on failure.
-+ */
-+int
-+ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
-+ const char *name, const void *value, size_t value_len, int flags)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct buffer_head *bh = NULL;
-+ struct ext3_xattr_header *header = NULL;
-+ struct ext3_xattr_entry *here, *last;
-+ unsigned int name_len;
-+ int block = EXT3_I(inode)->i_file_acl;
-+ int min_offs = sb->s_blocksize, not_found = 1, free, error;
-+ char *end;
-+
-+ /*
-+ * header -- Points either into bh, or to a temporarily
-+ * allocated buffer.
-+ * here -- The named entry found, or the place for inserting, within
-+ * the block pointed to by header.
-+ * last -- Points right after the last named entry within the block
-+ * pointed to by header.
-+ * min_offs -- The offset of the first value (values are aligned
-+ * towards the end of the block).
-+ * end -- Points right after the block pointed to by header.
-+ */
-+
-+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
-+ name_index, name, value, (long)value_len);
-+
-+ if (IS_RDONLY(inode))
-+ return -EROFS;
-+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-+ return -EPERM;
-+ if (value == NULL)
-+ value_len = 0;
-+ if (name == NULL)
-+ return -EINVAL;
-+ name_len = strlen(name);
-+ if (name_len > 255 || value_len > sb->s_blocksize)
-+ return -ERANGE;
-+ down(&ext3_xattr_sem);
-+
-+ if (block) {
-+ /* The inode already has an extended attribute block. */
-+ bh = sb_bread(sb, block);
-+ error = -EIO;
-+ if (!bh)
-+ goto cleanup;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)),
-+ le32_to_cpu(HDR(bh)->h_refcount));
-+ header = HDR(bh);
-+ end = bh->b_data + bh->b_size;
-+ if (header->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ header->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext3_error(sb, "ext3_xattr_set",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* Find the named attribute. */
-+ here = FIRST_ENTRY(bh);
-+ while (!IS_LAST_ENTRY(here)) {
-+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(here);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (!here->e_value_block && here->e_value_size) {
-+ int offs = le16_to_cpu(here->e_value_offs);
-+ if (offs < min_offs)
-+ min_offs = offs;
-+ }
-+ not_found = name_index - here->e_name_index;
-+ if (!not_found)
-+ not_found = name_len - here->e_name_len;
-+ if (!not_found)
-+ not_found = memcmp(name, here->e_name,name_len);
-+ if (not_found <= 0)
-+ break;
-+ here = next;
-+ }
-+ last = here;
-+ /* We still need to compute min_offs and last. */
-+ while (!IS_LAST_ENTRY(last)) {
-+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (!last->e_value_block && last->e_value_size) {
-+ int offs = le16_to_cpu(last->e_value_offs);
-+ if (offs < min_offs)
-+ min_offs = offs;
-+ }
-+ last = next;
-+ }
-+
-+ /* Check whether we have enough space left. */
-+ free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
-+ } else {
-+ /* We will use a new extended attribute block. */
-+ free = sb->s_blocksize -
-+ sizeof(struct ext3_xattr_header) - sizeof(__u32);
-+ here = last = NULL; /* avoid gcc uninitialized warning. */
-+ }
-+
-+ if (not_found) {
-+ /* Request to remove a nonexistent attribute? */
-+ error = -ENOATTR;
-+ if (flags & XATTR_REPLACE)
-+ goto cleanup;
-+ error = 0;
-+ if (value == NULL)
-+ goto cleanup;
-+ else
-+ free -= EXT3_XATTR_LEN(name_len);
-+ } else {
-+ /* Request to create an existing attribute? */
-+ error = -EEXIST;
-+ if (flags & XATTR_CREATE)
-+ goto cleanup;
-+ if (!here->e_value_block && here->e_value_size) {
-+ unsigned int size = le32_to_cpu(here->e_value_size);
-+
-+ if (le16_to_cpu(here->e_value_offs) + size >
-+ sb->s_blocksize || size > sb->s_blocksize)
-+ goto bad_block;
-+ free += EXT3_XATTR_SIZE(size);
-+ }
-+ }
-+ free -= EXT3_XATTR_SIZE(value_len);
-+ error = -ENOSPC;
-+ if (free < 0)
-+ goto cleanup;
-+
-+ /* Here we know that we can set the new attribute. */
-+
-+ if (header) {
-+ if (header->h_refcount == cpu_to_le32(1)) {
-+ ea_bdebug(bh, "modifying in-place");
-+ ext3_xattr_cache_remove(bh);
-+ error = ext3_journal_get_write_access(handle, bh);
-+ if (error)
-+ goto cleanup;
-+ } else {
-+ int offset;
-+
-+ ea_bdebug(bh, "cloning");
-+ header = kmalloc(bh->b_size, GFP_KERNEL);
-+ error = -ENOMEM;
-+ if (header == NULL)
-+ goto cleanup;
-+ memcpy(header, HDR(bh), bh->b_size);
-+ header->h_refcount = cpu_to_le32(1);
-+ offset = (char *)header - bh->b_data;
-+ here = ENTRY((char *)here + offset);
-+ last = ENTRY((char *)last + offset);
-+ }
-+ } else {
-+ /* Allocate a buffer where we construct the new block. */
-+ header = kmalloc(sb->s_blocksize, GFP_KERNEL);
-+ error = -ENOMEM;
-+ if (header == NULL)
-+ goto cleanup;
-+ memset(header, 0, sb->s_blocksize);
-+ end = (char *)header + sb->s_blocksize;
-+ header->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC);
-+ header->h_blocks = header->h_refcount = cpu_to_le32(1);
-+ last = here = ENTRY(header+1);
-+ }
-+
-+ if (not_found) {
-+ /* Insert the new name. */
-+ int size = EXT3_XATTR_LEN(name_len);
-+ int rest = (char *)last - (char *)here;
-+ memmove((char *)here + size, here, rest);
-+ memset(here, 0, size);
-+ here->e_name_index = name_index;
-+ here->e_name_len = name_len;
-+ memcpy(here->e_name, name, name_len);
-+ } else {
-+ /* Remove the old value. */
-+ if (!here->e_value_block && here->e_value_size) {
-+ char *first_val = (char *)header + min_offs;
-+ int offs = le16_to_cpu(here->e_value_offs);
-+ char *val = (char *)header + offs;
-+ size_t size = EXT3_XATTR_SIZE(
-+ le32_to_cpu(here->e_value_size));
-+ memmove(first_val + size, first_val, val - first_val);
-+ memset(first_val, 0, size);
-+ here->e_value_offs = 0;
-+ min_offs += size;
-+
-+ /* Adjust all value offsets. */
-+ last = ENTRY(header+1);
-+ while (!IS_LAST_ENTRY(last)) {
-+ int o = le16_to_cpu(last->e_value_offs);
-+ if (!last->e_value_block && o < offs)
-+ last->e_value_offs =
-+ cpu_to_le16(o + size);
-+ last = EXT3_XATTR_NEXT(last);
-+ }
-+ }
-+ if (value == NULL) {
-+ /* Remove this attribute. */
-+ if (EXT3_XATTR_NEXT(ENTRY(header+1)) == last) {
-+ /* This block is now empty. */
-+ error = ext3_xattr_set2(handle, inode, bh,NULL);
-+ goto cleanup;
-+ } else {
-+ /* Remove the old name. */
-+ int size = EXT3_XATTR_LEN(name_len);
-+ last = ENTRY((char *)last - size);
-+ memmove(here, (char*)here + size,
-+ (char*)last - (char*)here);
-+ memset(last, 0, size);
-+ }
-+ }
-+ }
-+
-+ if (value != NULL) {
-+ /* Insert the new value. */
-+ here->e_value_size = cpu_to_le32(value_len);
-+ if (value_len) {
-+ size_t size = EXT3_XATTR_SIZE(value_len);
-+ char *val = (char *)header + min_offs - size;
-+ here->e_value_offs =
-+ cpu_to_le16((char *)val - (char *)header);
-+ memset(val + size - EXT3_XATTR_PAD, 0,
-+ EXT3_XATTR_PAD); /* Clear the pad bytes. */
-+ memcpy(val, value, value_len);
-+ }
-+ }
-+ ext3_xattr_rehash(header, here);
-+
-+ error = ext3_xattr_set2(handle, inode, bh, header);
-+
-+cleanup:
-+ brelse(bh);
-+ if (!(bh && header == HDR(bh)))
-+ kfree(header);
-+ up(&ext3_xattr_sem);
-+
-+ return error;
-+}
-+
-+/*
-+ * Second half of ext3_xattr_set(): Update the file system.
-+ */
-+static int
-+ext3_xattr_set2(handle_t *handle, struct inode *inode,
-+ struct buffer_head *old_bh, struct ext3_xattr_header *header)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct buffer_head *new_bh = NULL;
-+ int error;
-+
-+ if (header) {
-+ new_bh = ext3_xattr_cache_find(inode, header);
-+ if (new_bh) {
-+ /*
-+ * We found an identical block in the cache.
-+ * The old block will be released after updating
-+ * the inode.
-+ */
-+ ea_bdebug(old_bh, "reusing block %ld",
-+ new_bh->b_blocknr);
-+
-+ error = -EDQUOT;
-+ if (ext3_xattr_quota_alloc(inode, 1))
-+ goto cleanup;
-+
-+ error = ext3_journal_get_write_access(handle, new_bh);
-+ if (error)
-+ goto cleanup;
-+ HDR(new_bh)->h_refcount = cpu_to_le32(
-+ le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
-+ ea_bdebug(new_bh, "refcount now=%d",
-+ le32_to_cpu(HDR(new_bh)->h_refcount));
-+ } else if (old_bh && header == HDR(old_bh)) {
-+ /* Keep this block. */
-+ new_bh = old_bh;
-+ (void)ext3_xattr_cache_insert(new_bh);
-+ } else {
-+ /* We need to allocate a new block */
-+ int force = EXT3_I(inode)->i_file_acl != 0;
-+ int block = ext3_xattr_new_block(handle, inode,
-+ &error, force);
-+ if (error)
-+ goto cleanup;
-+ ea_idebug(inode, "creating block %d", block);
-+
-+ new_bh = sb_getblk(sb, block);
-+ if (!new_bh) {
-+getblk_failed: ext3_xattr_free_block(handle, inode, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ lock_buffer(new_bh);
-+ error = ext3_journal_get_create_access(handle, new_bh);
-+ if (error) {
-+ unlock_buffer(new_bh);
-+ goto getblk_failed;
-+ }
-+ memcpy(new_bh->b_data, header, new_bh->b_size);
-+ mark_buffer_uptodate(new_bh, 1);
-+ unlock_buffer(new_bh);
-+ (void)ext3_xattr_cache_insert(new_bh);
-+
-+ ext3_xattr_update_super_block(handle, sb);
-+ }
-+ error = ext3_journal_dirty_metadata(handle, new_bh);
-+ if (error)
-+ goto cleanup;
-+ }
-+
-+ /* Update the inode. */
-+ EXT3_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
-+ inode->i_ctime = CURRENT_TIME;
-+ ext3_mark_inode_dirty(handle, inode);
-+ if (IS_SYNC(inode))
-+ handle->h_sync = 1;
-+
-+ error = 0;
-+ if (old_bh && old_bh != new_bh) {
-+ /*
-+ * If there was an old block, and we are not still using it,
-+ * we now release the old block.
-+ */
-+ unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
-+
-+ error = ext3_journal_get_write_access(handle, old_bh);
-+ if (error)
-+ goto cleanup;
-+ if (refcount == 1) {
-+ /* Free the old block. */
-+ ea_bdebug(old_bh, "freeing");
-+ ext3_xattr_free_block(handle, inode, old_bh->b_blocknr);
-+
-+ /* ext3_forget() calls bforget() for us, but we
-+ let our caller release old_bh, so we need to
-+ duplicate the handle before. */
-+ get_bh(old_bh);
-+ ext3_forget(handle, 1, inode, old_bh,old_bh->b_blocknr);
-+ } else {
-+ /* Decrement the refcount only. */
-+ refcount--;
-+ HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
-+ ext3_xattr_quota_free(inode);
-+ ext3_journal_dirty_metadata(handle, old_bh);
-+ ea_bdebug(old_bh, "refcount now=%d", refcount);
-+ }
-+ }
-+
-+cleanup:
-+ if (old_bh != new_bh)
-+ brelse(new_bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * ext3_xattr_delete_inode()
-+ *
-+ * Free extended attribute resources associated with this inode. This
-+ * is called immediately before an inode is freed.
-+ */
-+void
-+ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
-+{
-+ struct buffer_head *bh;
-+ unsigned int block = EXT3_I(inode)->i_file_acl;
-+
-+ if (!block)
-+ return;
-+ down(&ext3_xattr_sem);
-+
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh) {
-+ ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
-+ "inode %ld: block %d read error", inode->i_ino, block);
-+ goto cleanup;
-+ }
-+ ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+ ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ goto cleanup;
-+ }
-+ ext3_journal_get_write_access(handle, bh);
-+ ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
-+ if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
-+ ext3_xattr_cache_remove(bh);
-+ ext3_xattr_free_block(handle, inode, block);
-+ ext3_forget(handle, 1, inode, bh, block);
-+ bh = NULL;
-+ } else {
-+ HDR(bh)->h_refcount = cpu_to_le32(
-+ le32_to_cpu(HDR(bh)->h_refcount) - 1);
-+ ext3_journal_dirty_metadata(handle, bh);
-+ if (IS_SYNC(inode))
-+ handle->h_sync = 1;
-+ ext3_xattr_quota_free(inode);
-+ }
-+ EXT3_I(inode)->i_file_acl = 0;
-+
-+cleanup:
-+ brelse(bh);
-+ up(&ext3_xattr_sem);
-+}
-+
-+/*
-+ * ext3_xattr_put_super()
-+ *
-+ * This is called when a file system is unmounted.
-+ */
-+void
-+ext3_xattr_put_super(struct super_block *sb)
-+{
-+#ifdef CONFIG_EXT3_FS_XATTR_SHARING
-+ mb_cache_shrink(ext3_xattr_cache, sb->s_dev);
-+#endif
-+}
-+
-+#ifdef CONFIG_EXT3_FS_XATTR_SHARING
-+
-+/*
-+ * ext3_xattr_cache_insert()
-+ *
-+ * Create a new entry in the extended attribute cache, and insert
-+ * it unless such an entry is already in the cache.
-+ *
-+ * Returns 0, or a negative error number on failure.
-+ */
-+static int
-+ext3_xattr_cache_insert(struct buffer_head *bh)
-+{
-+ __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
-+ struct mb_cache_entry *ce;
-+ int error;
-+
-+ ce = mb_cache_entry_alloc(ext3_xattr_cache);
-+ if (!ce)
-+ return -ENOMEM;
-+ error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
-+ if (error) {
-+ mb_cache_entry_free(ce);
-+ if (error == -EBUSY) {
-+ ea_bdebug(bh, "already in cache (%d cache entries)",
-+ atomic_read(&ext3_xattr_cache->c_entry_count));
-+ error = 0;
-+ }
-+ } else {
-+ ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
-+ atomic_read(&ext3_xattr_cache->c_entry_count));
-+ mb_cache_entry_release(ce);
-+ }
-+ return error;
-+}
-+
-+/*
-+ * ext3_xattr_cmp()
-+ *
-+ * Compare two extended attribute blocks for equality.
-+ *
-+ * Returns 0 if the blocks are equal, 1 if they differ, and
-+ * a negative error number on errors.
-+ */
-+static int
-+ext3_xattr_cmp(struct ext3_xattr_header *header1,
-+ struct ext3_xattr_header *header2)
-+{
-+ struct ext3_xattr_entry *entry1, *entry2;
-+
-+ entry1 = ENTRY(header1+1);
-+ entry2 = ENTRY(header2+1);
-+ while (!IS_LAST_ENTRY(entry1)) {
-+ if (IS_LAST_ENTRY(entry2))
-+ return 1;
-+ if (entry1->e_hash != entry2->e_hash ||
-+ entry1->e_name_len != entry2->e_name_len ||
-+ entry1->e_value_size != entry2->e_value_size ||
-+ memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
-+ return 1;
-+ if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
-+ return -EIO;
-+ if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
-+ (char *)header2 + le16_to_cpu(entry2->e_value_offs),
-+ le32_to_cpu(entry1->e_value_size)))
-+ return 1;
-+
-+ entry1 = EXT3_XATTR_NEXT(entry1);
-+ entry2 = EXT3_XATTR_NEXT(entry2);
-+ }
-+ if (!IS_LAST_ENTRY(entry2))
-+ return 1;
-+ return 0;
-+}
-+
-+/*
-+ * ext3_xattr_cache_find()
-+ *
-+ * Find an identical extended attribute block.
-+ *
-+ * Returns a pointer to the block found, or NULL if such a block was
-+ * not found or an error occurred.
-+ */
-+static struct buffer_head *
-+ext3_xattr_cache_find(struct inode *inode, struct ext3_xattr_header *header)
-+{
-+ __u32 hash = le32_to_cpu(header->h_hash);
-+ struct mb_cache_entry *ce;
-+
-+ if (!header->h_hash)
-+ return NULL; /* never share */
-+ ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
-+ ce = mb_cache_entry_find_first(ext3_xattr_cache, 0, inode->i_dev, hash);
-+ while (ce) {
-+ struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
-+
-+ if (!bh) {
-+ ext3_error(inode->i_sb, "ext3_xattr_cache_find",
-+ "inode %ld: block %ld read error",
-+ inode->i_ino, ce->e_block);
-+ } else if (le32_to_cpu(HDR(bh)->h_refcount) >
-+ EXT3_XATTR_REFCOUNT_MAX) {
-+ ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
-+ le32_to_cpu(HDR(bh)->h_refcount),
-+ EXT3_XATTR_REFCOUNT_MAX);
-+ } else if (!ext3_xattr_cmp(header, HDR(bh))) {
-+ ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
-+ mb_cache_entry_release(ce);
-+ return bh;
-+ }
-+ brelse(bh);
-+ ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
-+ }
-+ return NULL;
-+}
-+
-+/*
-+ * ext3_xattr_cache_remove()
-+ *
-+ * Remove the cache entry of a block from the cache. Called when a
-+ * block becomes invalid.
-+ */
-+static void
-+ext3_xattr_cache_remove(struct buffer_head *bh)
-+{
-+ struct mb_cache_entry *ce;
-+
-+ ce = mb_cache_entry_get(ext3_xattr_cache, bh->b_dev, bh->b_blocknr);
-+ if (ce) {
-+ ea_bdebug(bh, "removing (%d cache entries remaining)",
-+ atomic_read(&ext3_xattr_cache->c_entry_count)-1);
-+ mb_cache_entry_free(ce);
-+ } else
-+ ea_bdebug(bh, "no cache entry");
-+}
-+
-+#define NAME_HASH_SHIFT 5
-+#define VALUE_HASH_SHIFT 16
-+
-+/*
-+ * ext3_xattr_hash_entry()
-+ *
-+ * Compute the hash of an extended attribute.
-+ */
-+static inline void ext3_xattr_hash_entry(struct ext3_xattr_header *header,
-+ struct ext3_xattr_entry *entry)
-+{
-+ __u32 hash = 0;
-+ char *name = entry->e_name;
-+ int n;
-+
-+ for (n=0; n < entry->e_name_len; n++) {
-+ hash = (hash << NAME_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
-+ *name++;
-+ }
-+
-+ if (entry->e_value_block == 0 && entry->e_value_size != 0) {
-+ __u32 *value = (__u32 *)((char *)header +
-+ le16_to_cpu(entry->e_value_offs));
-+ for (n = (le32_to_cpu(entry->e_value_size) +
-+ EXT3_XATTR_ROUND) >> EXT3_XATTR_PAD_BITS; n; n--) {
-+ hash = (hash << VALUE_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
-+ le32_to_cpu(*value++);
-+ }
-+ }
-+ entry->e_hash = cpu_to_le32(hash);
-+}
-+
-+#undef NAME_HASH_SHIFT
-+#undef VALUE_HASH_SHIFT
-+
-+#define BLOCK_HASH_SHIFT 16
-+
-+/*
-+ * ext3_xattr_rehash()
-+ *
-+ * Re-compute the extended attribute hash value after an entry has changed.
-+ */
-+static void ext3_xattr_rehash(struct ext3_xattr_header *header,
-+ struct ext3_xattr_entry *entry)
-+{
-+ struct ext3_xattr_entry *here;
-+ __u32 hash = 0;
-+
-+ ext3_xattr_hash_entry(header, entry);
-+ here = ENTRY(header+1);
-+ while (!IS_LAST_ENTRY(here)) {
-+ if (!here->e_hash) {
-+ /* Block is not shared if an entry's hash value == 0 */
-+ hash = 0;
-+ break;
-+ }
-+ hash = (hash << BLOCK_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
-+ le32_to_cpu(here->e_hash);
-+ here = EXT3_XATTR_NEXT(here);
-+ }
-+ header->h_hash = cpu_to_le32(hash);
-+}
-+
-+#undef BLOCK_HASH_SHIFT
-+
-+int __init
-+init_ext3_xattr(void)
-+{
-+ ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL,
-+ sizeof(struct mb_cache_entry) +
-+ sizeof(struct mb_cache_entry_index), 1, 61);
-+ if (!ext3_xattr_cache)
-+ return -ENOMEM;
-+
-+ return 0;
-+}
-+
-+void
-+exit_ext3_xattr(void)
-+{
-+ if (ext3_xattr_cache)
-+ mb_cache_destroy(ext3_xattr_cache);
-+ ext3_xattr_cache = NULL;
-+}
-+
-+#else /* CONFIG_EXT3_FS_XATTR_SHARING */
-+
-+int __init
-+init_ext3_xattr(void)
-+{
-+ return 0;
-+}
-+
-+void
-+exit_ext3_xattr(void)
-+{
-+}
-+
-+#endif /* CONFIG_EXT3_FS_XATTR_SHARING */
-Index: linux-2.4.24-vanilla/fs/ext3/xattr_user.c
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/ext3/xattr_user.c 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.24-vanilla/fs/ext3/xattr_user.c 2004-01-10 17:20:28.000000000 +0300
-@@ -0,0 +1,111 @@
-+/*
-+ * linux/fs/ext3/xattr_user.c
-+ * Handler for extended user attributes.
-+ *
-+ * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/string.h>
-+#include <linux/fs.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/ext3_fs.h>
-+#include <linux/ext3_xattr.h>
-+
-+#ifdef CONFIG_EXT3_FS_POSIX_ACL
-+# include <linux/ext3_acl.h>
-+#endif
-+
-+#define XATTR_USER_PREFIX "user."
-+
-+static size_t
-+ext3_xattr_user_list(char *list, struct inode *inode,
-+ const char *name, int name_len)
-+{
-+ const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
-+
-+ if (!test_opt(inode->i_sb, XATTR_USER))
-+ return 0;
-+
-+ if (list) {
-+ memcpy(list, XATTR_USER_PREFIX, prefix_len);
-+ memcpy(list+prefix_len, name, name_len);
-+ list[prefix_len + name_len] = '\0';
-+ }
-+ return prefix_len + name_len + 1;
-+}
-+
-+static int
-+ext3_xattr_user_get(struct inode *inode, const char *name,
-+ void *buffer, size_t size)
-+{
-+ int error;
-+
-+ if (strcmp(name, "") == 0)
-+ return -EINVAL;
-+ if (!test_opt(inode->i_sb, XATTR_USER))
-+ return -ENOTSUP;
-+#ifdef CONFIG_EXT3_FS_POSIX_ACL
-+ error = ext3_permission_locked(inode, MAY_READ);
-+#else
-+ error = permission(inode, MAY_READ);
-+#endif
-+ if (error)
-+ return error;
-+
-+ return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name,
-+ buffer, size);
-+}
-+
-+static int
-+ext3_xattr_user_set(struct inode *inode, const char *name,
-+ const void *value, size_t size, int flags)
-+{
-+ handle_t *handle;
-+ int error;
-+
-+ if (strcmp(name, "") == 0)
-+ return -EINVAL;
-+ if (!test_opt(inode->i_sb, XATTR_USER))
-+ return -ENOTSUP;
-+ if ( !S_ISREG(inode->i_mode) &&
-+ (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
-+ return -EPERM;
-+#ifdef CONFIG_EXT3_FS_POSIX_ACL
-+ error = ext3_permission_locked(inode, MAY_WRITE);
-+#else
-+ error = permission(inode, MAY_WRITE);
-+#endif
-+ if (error)
-+ return error;
-+
-+ handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
-+ if (IS_ERR(handle))
-+ return PTR_ERR(handle);
-+ error = ext3_xattr_set(handle, inode, EXT3_XATTR_INDEX_USER, name,
-+ value, size, flags);
-+ ext3_journal_stop(handle, inode);
-+
-+ return error;
-+}
-+
-+struct ext3_xattr_handler ext3_xattr_user_handler = {
-+ prefix: XATTR_USER_PREFIX,
-+ list: ext3_xattr_user_list,
-+ get: ext3_xattr_user_get,
-+ set: ext3_xattr_user_set,
-+};
-+
-+int __init
-+init_ext3_xattr_user(void)
-+{
-+ return ext3_xattr_register(EXT3_XATTR_INDEX_USER,
-+ &ext3_xattr_user_handler);
-+}
-+
-+void
-+exit_ext3_xattr_user(void)
-+{
-+ ext3_xattr_unregister(EXT3_XATTR_INDEX_USER,
-+ &ext3_xattr_user_handler);
-+}
-Index: linux-2.4.24-vanilla/fs/ext3/ext3-exports.c
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/ext3/ext3-exports.c 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.24-vanilla/fs/ext3/ext3-exports.c 2004-01-10 17:20:28.000000000 +0300
-@@ -0,0 +1,13 @@
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/ext3_fs.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/ext3_xattr.h>
-+
-+EXPORT_SYMBOL(ext3_force_commit);
-+EXPORT_SYMBOL(ext3_bread);
-+EXPORT_SYMBOL(ext3_xattr_register);
-+EXPORT_SYMBOL(ext3_xattr_unregister);
-+EXPORT_SYMBOL(ext3_xattr_get);
-+EXPORT_SYMBOL(ext3_xattr_list);
-+EXPORT_SYMBOL(ext3_xattr_set);
-Index: linux-2.4.24-vanilla/fs/jfs/jfs_xattr.h
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/jfs/jfs_xattr.h 2003-05-16 05:29:12.000000000 +0400
-+++ linux-2.4.24-vanilla/fs/jfs/jfs_xattr.h 2004-01-10 17:20:28.000000000 +0300
-@@ -52,8 +52,10 @@
- #define END_EALIST(ealist) \
- ((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist)))
-
--extern int __jfs_setxattr(struct inode *, const char *, void *, size_t, int);
--extern int jfs_setxattr(struct dentry *, const char *, void *, size_t, int);
-+extern int __jfs_setxattr(struct inode *, const char *, const void *, size_t,
-+ int);
-+extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t,
-+ int);
- extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t);
- extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t);
- extern ssize_t jfs_listxattr(struct dentry *, char *, size_t);
-Index: linux-2.4.24-vanilla/fs/jfs/xattr.c
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/jfs/xattr.c 2004-01-10 17:05:55.000000000 +0300
-+++ linux-2.4.24-vanilla/fs/jfs/xattr.c 2004-01-10 17:20:28.000000000 +0300
-@@ -648,7 +648,7 @@
- }
-
- static int can_set_xattr(struct inode *inode, const char *name,
-- void *value, size_t value_len)
-+ const void *value, size_t value_len)
- {
- if (IS_RDONLY(inode))
- return -EROFS;
-@@ -667,7 +667,7 @@
- return permission(inode, MAY_WRITE);
- }
-
--int __jfs_setxattr(struct inode *inode, const char *name, void *value,
-+int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
- size_t value_len, int flags)
- {
- struct jfs_ea_list *ealist;
-@@ -806,7 +806,7 @@
- return rc;
- }
-
--int jfs_setxattr(struct dentry *dentry, const char *name, void *value,
-+int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
- size_t value_len, int flags)
- {
- if (value == NULL) { /* empty EA, do not remove */
-Index: linux-2.4.24-vanilla/fs/mbcache.c
-===================================================================
---- linux-2.4.24-vanilla.orig/fs/mbcache.c 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.24-vanilla/fs/mbcache.c 2004-01-10 17:20:28.000000000 +0300
-@@ -0,0 +1,648 @@
-+/*
-+ * linux/fs/mbcache.c
-+ * (C) 2001-2002 Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ */
-+
-+/*
-+ * Filesystem Meta Information Block Cache (mbcache)
-+ *
-+ * The mbcache caches blocks of block devices that need to be located
-+ * by their device/block number, as well as by other criteria (such
-+ * as the block's contents).
-+ *
-+ * There can only be one cache entry in a cache per device and block number.
-+ * Additional indexes need not be unique in this sense. The number of
-+ * additional indexes (=other criteria) can be hardwired at compile time
-+ * or specified at cache create time.
-+ *
-+ * Each cache entry is of fixed size. An entry may be `valid' or `invalid'
-+ * in the cache. A valid entry is in the main hash tables of the cache,
-+ * and may also be in the lru list. An invalid entry is not in any hashes
-+ * or lists.
-+ *
-+ * A valid cache entry is only in the lru list if no handles refer to it.
-+ * Invalid cache entries will be freed when the last handle to the cache
-+ * entry is released. Entries that cannot be freed immediately are put
-+ * back on the lru list.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+
-+#include <linux/fs.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/cache_def.h>
-+#include <linux/version.h>
-+#include <linux/init.h>
-+#include <linux/mbcache.h>
-+
-+
-+#ifdef MB_CACHE_DEBUG
-+# define mb_debug(f...) do { \
-+ printk(KERN_DEBUG f); \
-+ printk("\n"); \
-+ } while (0)
-+#define mb_assert(c) do { if (!(c)) \
-+ printk(KERN_ERR "assertion " #c " failed\n"); \
-+ } while(0)
-+#else
-+# define mb_debug(f...) do { } while(0)
-+# define mb_assert(c) do { } while(0)
-+#endif
-+#define mb_error(f...) do { \
-+ printk(KERN_ERR f); \
-+ printk("\n"); \
-+ } while(0)
-+
-+MODULE_AUTHOR("Andreas Gruenbacher <a.gruenbacher@computer.org>");
-+MODULE_DESCRIPTION("Meta block cache (for extended attributes)");
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-+MODULE_LICENSE("GPL");
-+#endif
-+
-+EXPORT_SYMBOL(mb_cache_create);
-+EXPORT_SYMBOL(mb_cache_shrink);
-+EXPORT_SYMBOL(mb_cache_destroy);
-+EXPORT_SYMBOL(mb_cache_entry_alloc);
-+EXPORT_SYMBOL(mb_cache_entry_insert);
-+EXPORT_SYMBOL(mb_cache_entry_release);
-+EXPORT_SYMBOL(mb_cache_entry_takeout);
-+EXPORT_SYMBOL(mb_cache_entry_free);
-+EXPORT_SYMBOL(mb_cache_entry_dup);
-+EXPORT_SYMBOL(mb_cache_entry_get);
-+#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
-+EXPORT_SYMBOL(mb_cache_entry_find_first);
-+EXPORT_SYMBOL(mb_cache_entry_find_next);
-+#endif
-+
-+
-+/*
-+ * Global data: list of all mbcache's, lru list, and a spinlock for
-+ * accessing cache data structures on SMP machines. The lru list is
-+ * global across all mbcaches.
-+ */
-+
-+static LIST_HEAD(mb_cache_list);
-+static LIST_HEAD(mb_cache_lru_list);
-+static spinlock_t mb_cache_spinlock = SPIN_LOCK_UNLOCKED;
-+
-+static inline int
-+mb_cache_indexes(struct mb_cache *cache)
-+{
-+#ifdef MB_CACHE_INDEXES_COUNT
-+ return MB_CACHE_INDEXES_COUNT;
-+#else
-+ return cache->c_indexes_count;
-+#endif
-+}
-+
-+/*
-+ * What the mbcache registers as to get shrunk dynamically.
-+ */
-+
-+static void
-+mb_cache_memory_pressure(int priority, unsigned int gfp_mask);
-+
-+static struct cache_definition mb_cache_definition = {
-+ "mb_cache",
-+ mb_cache_memory_pressure
-+};
-+
-+
-+static inline int
-+__mb_cache_entry_is_hashed(struct mb_cache_entry *ce)
-+{
-+ return !list_empty(&ce->e_block_list);
-+}
-+
-+
-+static inline void
-+__mb_cache_entry_unhash(struct mb_cache_entry *ce)
-+{
-+ int n;
-+
-+ if (__mb_cache_entry_is_hashed(ce)) {
-+ list_del_init(&ce->e_block_list);
-+ for (n=0; n<mb_cache_indexes(ce->e_cache); n++)
-+ list_del(&ce->e_indexes[n].o_list);
-+ }
-+}
-+
-+
-+static inline void
-+__mb_cache_entry_forget(struct mb_cache_entry *ce, int gfp_mask)
-+{
-+ struct mb_cache *cache = ce->e_cache;
-+
-+ mb_assert(atomic_read(&ce->e_used) == 0);
-+ if (cache->c_op.free && cache->c_op.free(ce, gfp_mask)) {
-+ /* free failed -- put back on the lru list
-+ for freeing later. */
-+ spin_lock(&mb_cache_spinlock);
-+ list_add(&ce->e_lru_list, &mb_cache_lru_list);
-+ spin_unlock(&mb_cache_spinlock);
-+ } else {
-+ kmem_cache_free(cache->c_entry_cache, ce);
-+ atomic_dec(&cache->c_entry_count);
-+ }
-+}
-+
-+
-+static inline void
-+__mb_cache_entry_release_unlock(struct mb_cache_entry *ce)
-+{
-+ if (atomic_dec_and_test(&ce->e_used)) {
-+ if (__mb_cache_entry_is_hashed(ce))
-+ list_add_tail(&ce->e_lru_list, &mb_cache_lru_list);
-+ else {
-+ spin_unlock(&mb_cache_spinlock);
-+ __mb_cache_entry_forget(ce, GFP_KERNEL);
-+ return;
-+ }
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+}
-+
-+
-+/*
-+ * mb_cache_memory_pressure() memory pressure callback
-+ *
-+ * This function is called by the kernel memory management when memory
-+ * gets low.
-+ *
-+ * @priority: Amount by which to shrink the cache (0 = highes priority)
-+ * @gfp_mask: (ignored)
-+ */
-+static void
-+mb_cache_memory_pressure(int priority, unsigned int gfp_mask)
-+{
-+ LIST_HEAD(free_list);
-+ struct list_head *l, *ltmp;
-+ int count = 0;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each(l, &mb_cache_list) {
-+ struct mb_cache *cache =
-+ list_entry(l, struct mb_cache, c_cache_list);
-+ mb_debug("cache %s (%d)", cache->c_name,
-+ atomic_read(&cache->c_entry_count));
-+ count += atomic_read(&cache->c_entry_count);
-+ }
-+ mb_debug("trying to free %d of %d entries",
-+ count / (priority ? priority : 1), count);
-+ if (priority)
-+ count /= priority;
-+ while (count-- && !list_empty(&mb_cache_lru_list)) {
-+ struct mb_cache_entry *ce =
-+ list_entry(mb_cache_lru_list.next,
-+ struct mb_cache_entry, e_lru_list);
-+ list_del(&ce->e_lru_list);
-+ __mb_cache_entry_unhash(ce);
-+ list_add_tail(&ce->e_lru_list, &free_list);
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+ list_for_each_safe(l, ltmp, &free_list) {
-+ __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
-+ e_lru_list), gfp_mask);
-+ }
-+}
-+
-+
-+/*
-+ * mb_cache_create() create a new cache
-+ *
-+ * All entries in one cache are equal size. Cache entries may be from
-+ * multiple devices. If this is the first mbcache created, registers
-+ * the cache with kernel memory management. Returns NULL if no more
-+ * memory was available.
-+ *
-+ * @name: name of the cache (informal)
-+ * @cache_op: contains the callback called when freeing a cache entry
-+ * @entry_size: The size of a cache entry, including
-+ * struct mb_cache_entry
-+ * @indexes_count: number of additional indexes in the cache. Must equal
-+ * MB_CACHE_INDEXES_COUNT if the number of indexes is
-+ * hardwired.
-+ * @bucket_count: number of hash buckets
-+ */
-+struct mb_cache *
-+mb_cache_create(const char *name, struct mb_cache_op *cache_op,
-+ size_t entry_size, int indexes_count, int bucket_count)
-+{
-+ int m=0, n;
-+ struct mb_cache *cache = NULL;
-+
-+ if(entry_size < sizeof(struct mb_cache_entry) +
-+ indexes_count * sizeof(struct mb_cache_entry_index))
-+ return NULL;
-+
-+ MOD_INC_USE_COUNT;
-+ cache = kmalloc(sizeof(struct mb_cache) +
-+ indexes_count * sizeof(struct list_head), GFP_KERNEL);
-+ if (!cache)
-+ goto fail;
-+ cache->c_name = name;
-+ cache->c_op.free = NULL;
-+ if (cache_op)
-+ cache->c_op.free = cache_op->free;
-+ atomic_set(&cache->c_entry_count, 0);
-+ cache->c_bucket_count = bucket_count;
-+#ifdef MB_CACHE_INDEXES_COUNT
-+ mb_assert(indexes_count == MB_CACHE_INDEXES_COUNT);
-+#else
-+ cache->c_indexes_count = indexes_count;
-+#endif
-+ cache->c_block_hash = kmalloc(bucket_count * sizeof(struct list_head),
-+ GFP_KERNEL);
-+ if (!cache->c_block_hash)
-+ goto fail;
-+ for (n=0; n<bucket_count; n++)
-+ INIT_LIST_HEAD(&cache->c_block_hash[n]);
-+ for (m=0; m<indexes_count; m++) {
-+ cache->c_indexes_hash[m] = kmalloc(bucket_count *
-+ sizeof(struct list_head),
-+ GFP_KERNEL);
-+ if (!cache->c_indexes_hash[m])
-+ goto fail;
-+ for (n=0; n<bucket_count; n++)
-+ INIT_LIST_HEAD(&cache->c_indexes_hash[m][n]);
-+ }
-+ cache->c_entry_cache = kmem_cache_create(name, entry_size, 0,
-+ 0 /*SLAB_POISON | SLAB_RED_ZONE*/, NULL, NULL);
-+ if (!cache->c_entry_cache)
-+ goto fail;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ list_add(&cache->c_cache_list, &mb_cache_list);
-+ spin_unlock(&mb_cache_spinlock);
-+ return cache;
-+
-+fail:
-+ if (cache) {
-+ while (--m >= 0)
-+ kfree(cache->c_indexes_hash[m]);
-+ if (cache->c_block_hash)
-+ kfree(cache->c_block_hash);
-+ kfree(cache);
-+ }
-+ MOD_DEC_USE_COUNT;
-+ return NULL;
-+}
-+
-+
-+/*
-+ * mb_cache_shrink()
-+ *
-+ * Removes all cache entires of a device from the cache. All cache entries
-+ * currently in use cannot be freed, and thus remain in the cache.
-+ *
-+ * @cache: which cache to shrink
-+ * @dev: which device's cache entries to shrink
-+ */
-+void
-+mb_cache_shrink(struct mb_cache *cache, kdev_t dev)
-+{
-+ LIST_HEAD(free_list);
-+ struct list_head *l, *ltmp;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_lru_list);
-+ if (ce->e_dev == dev) {
-+ list_del(&ce->e_lru_list);
-+ list_add_tail(&ce->e_lru_list, &free_list);
-+ __mb_cache_entry_unhash(ce);
-+ }
-+ }
-+ spin_unlock(&mb_cache_spinlock);
-+ list_for_each_safe(l, ltmp, &free_list) {
-+ __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
-+ e_lru_list), GFP_KERNEL);
-+ }
-+}
-+
-+
-+/*
-+ * mb_cache_destroy()
-+ *
-+ * Shrinks the cache to its minimum possible size (hopefully 0 entries),
-+ * and then destroys it. If this was the last mbcache, un-registers the
-+ * mbcache from kernel memory management.
-+ */
-+void
-+mb_cache_destroy(struct mb_cache *cache)
-+{
-+ LIST_HEAD(free_list);
-+ struct list_head *l, *ltmp;
-+ int n;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each_safe(l, ltmp, &mb_cache_lru_list) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_lru_list);
-+ if (ce->e_cache == cache) {
-+ list_del(&ce->e_lru_list);
-+ list_add_tail(&ce->e_lru_list, &free_list);
-+ __mb_cache_entry_unhash(ce);
-+ }
-+ }
-+ list_del(&cache->c_cache_list);
-+ spin_unlock(&mb_cache_spinlock);
-+ list_for_each_safe(l, ltmp, &free_list) {
-+ __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry,
-+ e_lru_list), GFP_KERNEL);
-+ }
-+
-+ if (atomic_read(&cache->c_entry_count) > 0) {
-+ mb_error("cache %s: %d orphaned entries",
-+ cache->c_name,
-+ atomic_read(&cache->c_entry_count));
-+ }
-+
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
-+ /* We don't have kmem_cache_destroy() in 2.2.x */
-+ kmem_cache_shrink(cache->c_entry_cache);
-+#else
-+ kmem_cache_destroy(cache->c_entry_cache);
-+#endif
-+ for (n=0; n < mb_cache_indexes(cache); n++)
-+ kfree(cache->c_indexes_hash[n]);
-+ kfree(cache->c_block_hash);
-+ kfree(cache);
-+
-+ MOD_DEC_USE_COUNT;
-+}
-+
-+
-+/*
-+ * mb_cache_entry_alloc()
-+ *
-+ * Allocates a new cache entry. The new entry will not be valid initially,
-+ * and thus cannot be looked up yet. It should be filled with data, and
-+ * then inserted into the cache using mb_cache_entry_insert(). Returns NULL
-+ * if no more memory was available.
-+ */
-+struct mb_cache_entry *
-+mb_cache_entry_alloc(struct mb_cache *cache)
-+{
-+ struct mb_cache_entry *ce;
-+
-+ atomic_inc(&cache->c_entry_count);
-+ ce = kmem_cache_alloc(cache->c_entry_cache, GFP_KERNEL);
-+ if (ce) {
-+ INIT_LIST_HEAD(&ce->e_lru_list);
-+ INIT_LIST_HEAD(&ce->e_block_list);
-+ ce->e_cache = cache;
-+ atomic_set(&ce->e_used, 1);
-+ }
-+ return ce;
-+}
-+
-+
-+/*
-+ * mb_cache_entry_insert()
-+ *
-+ * Inserts an entry that was allocated using mb_cache_entry_alloc() into
-+ * the cache. After this, the cache entry can be looked up, but is not yet
-+ * in the lru list as the caller still holds a handle to it. Returns 0 on
-+ * success, or -EBUSY if a cache entry for that device + inode exists
-+ * already (this may happen after a failed lookup, if another process has
-+ * inserted the same cache entry in the meantime).
-+ *
-+ * @dev: device the cache entry belongs to
-+ * @block: block number
-+ * @keys: array of additional keys. There must be indexes_count entries
-+ * in the array (as specified when creating the cache).
-+ */
-+int
-+mb_cache_entry_insert(struct mb_cache_entry *ce, kdev_t dev,
-+ unsigned long block, unsigned int keys[])
-+{
-+ struct mb_cache *cache = ce->e_cache;
-+ unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
-+ struct list_head *l;
-+ int error = -EBUSY, n;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each(l, &cache->c_block_hash[bucket]) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry, e_block_list);
-+ if (ce->e_dev == dev && ce->e_block == block)
-+ goto out;
-+ }
-+ __mb_cache_entry_unhash(ce);
-+ ce->e_dev = dev;
-+ ce->e_block = block;
-+ list_add(&ce->e_block_list, &cache->c_block_hash[bucket]);
-+ for (n=0; n<mb_cache_indexes(cache); n++) {
-+ ce->e_indexes[n].o_key = keys[n];
-+ bucket = keys[n] % cache->c_bucket_count;
-+ list_add(&ce->e_indexes[n].o_list,
-+ &cache->c_indexes_hash[n][bucket]);
-+ }
-+out:
-+ spin_unlock(&mb_cache_spinlock);
-+ return error;
-+}
-+
-+
-+/*
-+ * mb_cache_entry_release()
-+ *
-+ * Release a handle to a cache entry. When the last handle to a cache entry
-+ * is released it is either freed (if it is invalid) or otherwise inserted
-+ * in to the lru list.
-+ */
-+void
-+mb_cache_entry_release(struct mb_cache_entry *ce)
-+{
-+ spin_lock(&mb_cache_spinlock);
-+ __mb_cache_entry_release_unlock(ce);
-+}
-+
-+
-+/*
-+ * mb_cache_entry_takeout()
-+ *
-+ * Take a cache entry out of the cache, making it invalid. The entry can later
-+ * be re-inserted using mb_cache_entry_insert(), or released using
-+ * mb_cache_entry_release().
-+ */
-+void
-+mb_cache_entry_takeout(struct mb_cache_entry *ce)
-+{
-+ spin_lock(&mb_cache_spinlock);
-+ mb_assert(list_empty(&ce->e_lru_list));
-+ __mb_cache_entry_unhash(ce);
-+ spin_unlock(&mb_cache_spinlock);
-+}
-+
-+
-+/*
-+ * mb_cache_entry_free()
-+ *
-+ * This is equivalent to the sequence mb_cache_entry_takeout() --
-+ * mb_cache_entry_release().
-+ */
-+void
-+mb_cache_entry_free(struct mb_cache_entry *ce)
-+{
-+ spin_lock(&mb_cache_spinlock);
-+ mb_assert(list_empty(&ce->e_lru_list));
-+ __mb_cache_entry_unhash(ce);
-+ __mb_cache_entry_release_unlock(ce);
-+}
-+
-+
-+/*
-+ * mb_cache_entry_dup()
-+ *
-+ * Duplicate a handle to a cache entry (does not duplicate the cache entry
-+ * itself). After the call, both the old and the new handle must be released.
-+ */
-+struct mb_cache_entry *
-+mb_cache_entry_dup(struct mb_cache_entry *ce)
-+{
-+ atomic_inc(&ce->e_used);
-+ return ce;
-+}
-+
-+
-+/*
-+ * mb_cache_entry_get()
-+ *
-+ * Get a cache entry by device / block number. (There can only be one entry
-+ * in the cache per device and block.) Returns NULL if no such cache entry
-+ * exists.
-+ */
-+struct mb_cache_entry *
-+mb_cache_entry_get(struct mb_cache *cache, kdev_t dev, unsigned long block)
-+{
-+ unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count;
-+ struct list_head *l;
-+ struct mb_cache_entry *ce;
-+
-+ spin_lock(&mb_cache_spinlock);
-+ list_for_each(l, &cache->c_block_hash[bucket]) {
-+ ce = list_entry(l, struct mb_cache_entry, e_block_list);
-+ if (ce->e_dev == dev && ce->e_block == block) {
-+ if (!list_empty(&ce->e_lru_list))
-+ list_del_init(&ce->e_lru_list);
-+ atomic_inc(&ce->e_used);
-+ goto cleanup;
-+ }
-+ }
-+ ce = NULL;
-+
-+cleanup:
-+ spin_unlock(&mb_cache_spinlock);
-+ return ce;
-+}
-+
-+#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
-+
-+static struct mb_cache_entry *
-+__mb_cache_entry_find(struct list_head *l, struct list_head *head,
-+ int index, kdev_t dev, unsigned int key)
-+{
-+ while (l != head) {
-+ struct mb_cache_entry *ce =
-+ list_entry(l, struct mb_cache_entry,
-+ e_indexes[index].o_list);
-+ if (ce->e_dev == dev && ce->e_indexes[index].o_key == key) {
-+ if (!list_empty(&ce->e_lru_list))
-+ list_del_init(&ce->e_lru_list);
-+ atomic_inc(&ce->e_used);
-+ return ce;
-+ }
-+ l = l->next;
-+ }
-+ return NULL;
-+}
-+
-+
-+/*
-+ * mb_cache_entry_find_first()
-+ *
-+ * Find the first cache entry on a given device with a certain key in
-+ * an additional index. Additonal matches can be found with
-+ * mb_cache_entry_find_next(). Returns NULL if no match was found.
-+ *
-+ * @cache: the cache to search
-+ * @index: the number of the additonal index to search (0<=index<indexes_count)
-+ * @dev: the device the cache entry should belong to
-+ * @key: the key in the index
-+ */
-+struct mb_cache_entry *
-+mb_cache_entry_find_first(struct mb_cache *cache, int index, kdev_t dev,
-+ unsigned int key)
-+{
-+ unsigned int bucket = key % cache->c_bucket_count;
-+ struct list_head *l;
-+ struct mb_cache_entry *ce;
-+
-+ mb_assert(index < mb_cache_indexes(cache));
-+ spin_lock(&mb_cache_spinlock);
-+ l = cache->c_indexes_hash[index][bucket].next;
-+ ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
-+ index, dev, key);
-+ spin_unlock(&mb_cache_spinlock);
-+ return ce;
-+}
-+
-+
-+/*
-+ * mb_cache_entry_find_next()
-+ *
-+ * Find the next cache entry on a given device with a certain key in an
-+ * additional index. Returns NULL if no match could be found. The previous
-+ * entry is atomatically released, so that mb_cache_entry_find_next() can
-+ * be called like this:
-+ *
-+ * entry = mb_cache_entry_find_first();
-+ * while (entry) {
-+ * ...
-+ * entry = mb_cache_entry_find_next(entry, ...);
-+ * }
-+ *
-+ * @prev: The previous match
-+ * @index: the number of the additonal index to search (0<=index<indexes_count)
-+ * @dev: the device the cache entry should belong to
-+ * @key: the key in the index
-+ */
-+struct mb_cache_entry *
-+mb_cache_entry_find_next(struct mb_cache_entry *prev, int index, kdev_t dev,
-+ unsigned int key)
-+{
-+ struct mb_cache *cache = prev->e_cache;
-+ unsigned int bucket = key % cache->c_bucket_count;
-+ struct list_head *l;
-+ struct mb_cache_entry *ce;
-+
-+ mb_assert(index < mb_cache_indexes(cache));
-+ spin_lock(&mb_cache_spinlock);
-+ l = prev->e_indexes[index].o_list.next;
-+ ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket],
-+ index, dev, key);
-+ __mb_cache_entry_release_unlock(prev);
-+ return ce;
-+}
-+
-+#endif /* !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) */
-+
-+static int __init init_mbcache(void)
-+{
-+ register_cache(&mb_cache_definition);
-+ return 0;
-+}
-+
-+static void __exit exit_mbcache(void)
-+{
-+ unregister_cache(&mb_cache_definition);
-+}
-+
-+module_init(init_mbcache)
-+module_exit(exit_mbcache)
-+
-Index: linux-2.4.24-vanilla/include/asm-arm/unistd.h
-===================================================================
---- linux-2.4.24-vanilla.orig/include/asm-arm/unistd.h 2004-01-10 17:05:06.000000000 +0300
-+++ linux-2.4.24-vanilla/include/asm-arm/unistd.h 2004-01-10 17:20:28.000000000 +0300
-@@ -250,7 +250,6 @@
- #define __NR_security (__NR_SYSCALL_BASE+223)
- #define __NR_gettid (__NR_SYSCALL_BASE+224)
- #define __NR_readahead (__NR_SYSCALL_BASE+225)
--#if 0 /* allocated in 2.5 */
- #define __NR_setxattr (__NR_SYSCALL_BASE+226)
- #define __NR_lsetxattr (__NR_SYSCALL_BASE+227)
- #define __NR_fsetxattr (__NR_SYSCALL_BASE+228)
-@@ -263,7 +262,6 @@
- #define __NR_removexattr (__NR_SYSCALL_BASE+235)
- #define __NR_lremovexattr (__NR_SYSCALL_BASE+236)
- #define __NR_fremovexattr (__NR_SYSCALL_BASE+237)
--#endif
- #define __NR_tkill (__NR_SYSCALL_BASE+238)
- #if 0 /* allocated in 2.5 */
- #define __NR_sendfile64 (__NR_SYSCALL_BASE+239)
-Index: linux-2.4.24-vanilla/include/asm-ppc64/unistd.h
-===================================================================
---- linux-2.4.24-vanilla.orig/include/asm-ppc64/unistd.h 2004-01-10 17:05:59.000000000 +0300
-+++ linux-2.4.24-vanilla/include/asm-ppc64/unistd.h 2004-01-10 17:20:28.000000000 +0300
-@@ -218,6 +218,7 @@
- #define __NR_mincore 206
- #define __NR_gettid 207
- #define __NR_tkill 208
-+#endif
- #define __NR_setxattr 209
- #define __NR_lsetxattr 210
- #define __NR_fsetxattr 211
-@@ -230,6 +231,7 @@
- #define __NR_removexattr 218
- #define __NR_lremovexattr 219
- #define __NR_fremovexattr 220
-+#if 0 /* Reserved syscalls */
- #define __NR_futex 221
- #define __NR_sched_setaffinity 222
- #define __NR_sched_getaffinity 223
-Index: linux-2.4.24-vanilla/include/asm-s390/unistd.h
-===================================================================
---- linux-2.4.24-vanilla.orig/include/asm-s390/unistd.h 2004-01-10 17:04:42.000000000 +0300
-+++ linux-2.4.24-vanilla/include/asm-s390/unistd.h 2004-01-10 17:20:28.000000000 +0300
-@@ -213,9 +213,18 @@
- #define __NR_getdents64 220
- #define __NR_fcntl64 221
- #define __NR_readahead 222
--/*
-- * Numbers 224-235 are reserved for posix acl
-- */
-+#define __NR_setxattr 224
-+#define __NR_lsetxattr 225
-+#define __NR_fsetxattr 226
-+#define __NR_getxattr 227
-+#define __NR_lgetxattr 228
-+#define __NR_fgetxattr 229
-+#define __NR_listxattr 230
-+#define __NR_llistxattr 231
-+#define __NR_flistxattr 232
-+#define __NR_removexattr 233
-+#define __NR_lremovexattr 234
-+#define __NR_fremovexattr 235
- #define __NR_gettid 236
- #define __NR_tkill 237
-
-Index: linux-2.4.24-vanilla/include/asm-s390x/unistd.h
-===================================================================
---- linux-2.4.24-vanilla.orig/include/asm-s390x/unistd.h 2004-01-10 17:04:42.000000000 +0300
-+++ linux-2.4.24-vanilla/include/asm-s390x/unistd.h 2004-01-10 17:20:28.000000000 +0300
-@@ -181,9 +181,18 @@
- #define __NR_mincore 218
- #define __NR_madvise 219
- #define __NR_readahead 222
--/*
-- * Numbers 224-235 are reserved for posix acl
-- */
-+#define __NR_setxattr 224
-+#define __NR_lsetxattr 225
-+#define __NR_fsetxattr 226
-+#define __NR_getxattr 227
-+#define __NR_lgetxattr 228
-+#define __NR_fgetxattr 229
-+#define __NR_listxattr 230
-+#define __NR_llistxattr 231
-+#define __NR_flistxattr 232
-+#define __NR_removexattr 233
-+#define __NR_lremovexattr 234
-+#define __NR_fremovexattr 235
- #define __NR_gettid 236
- #define __NR_tkill 237
-
-Index: linux-2.4.24-vanilla/include/linux/cache_def.h
-===================================================================
---- linux-2.4.24-vanilla.orig/include/linux/cache_def.h 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.24-vanilla/include/linux/cache_def.h 2004-01-10 17:20:28.000000000 +0300
-@@ -0,0 +1,15 @@
-+/*
-+ * linux/cache_def.h
-+ * Handling of caches defined in drivers, filesystems, ...
-+ *
-+ * Copyright (C) 2002 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ */
-+
-+struct cache_definition {
-+ const char *name;
-+ void (*shrink)(int, unsigned int);
-+ struct list_head link;
-+};
-+
-+extern void register_cache(struct cache_definition *);
-+extern void unregister_cache(struct cache_definition *);
-Index: linux-2.4.24-vanilla/include/linux/errno.h
-===================================================================
---- linux-2.4.24-vanilla.orig/include/linux/errno.h 2001-02-10 01:46:13.000000000 +0300
-+++ linux-2.4.24-vanilla/include/linux/errno.h 2004-01-10 17:20:28.000000000 +0300
-@@ -23,4 +23,8 @@
-
- #endif
-
-+/* Defined for extended attributes */
-+#define ENOATTR ENODATA /* No such attribute */
-+#define ENOTSUP EOPNOTSUPP /* Operation not supported */
-+
- #endif
-Index: linux-2.4.24-vanilla/include/linux/ext2_fs.h
-===================================================================
---- linux-2.4.24-vanilla.orig/include/linux/ext2_fs.h 2004-01-10 17:04:42.000000000 +0300
-+++ linux-2.4.24-vanilla/include/linux/ext2_fs.h 2004-01-10 17:20:28.000000000 +0300
-@@ -57,8 +57,6 @@
- */
- #define EXT2_BAD_INO 1 /* Bad blocks inode */
- #define EXT2_ROOT_INO 2 /* Root inode */
--#define EXT2_ACL_IDX_INO 3 /* ACL inode */
--#define EXT2_ACL_DATA_INO 4 /* ACL inode */
- #define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
- #define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
-
-@@ -86,7 +84,6 @@
- #else
- # define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
- #endif
--#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
- #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
- #ifdef __KERNEL__
- # define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
-@@ -121,28 +118,6 @@
- #endif
-
- /*
-- * ACL structures
-- */
--struct ext2_acl_header /* Header of Access Control Lists */
--{
-- __u32 aclh_size;
-- __u32 aclh_file_count;
-- __u32 aclh_acle_count;
-- __u32 aclh_first_acle;
--};
--
--struct ext2_acl_entry /* Access Control List Entry */
--{
-- __u32 acle_size;
-- __u16 acle_perms; /* Access permissions */
-- __u16 acle_type; /* Type of entry */
-- __u16 acle_tag; /* User or group identity */
-- __u16 acle_pad1;
-- __u32 acle_next; /* Pointer on next entry for the */
-- /* same inode or on next free entry */
--};
--
--/*
- * Structure of a blocks group descriptor
- */
- struct ext2_group_desc
-@@ -314,6 +289,7 @@
- #define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
- #define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
- #define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
-+#define EXT2_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
-
- #define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
- #define set_opt(o, opt) o |= EXT2_MOUNT_##opt
-@@ -397,6 +373,7 @@
-
- #ifdef __KERNEL__
- #define EXT2_SB(sb) (&((sb)->u.ext2_sb))
-+#define EXT2_I(inode) (&((inode)->u.ext2_i))
- #else
- /* Assume that user mode programs are passing in an ext2fs superblock, not
- * a kernel struct super_block. This will allow us to call the feature-test
-@@ -466,7 +443,7 @@
- #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008
- #define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff
-
--#define EXT2_FEATURE_COMPAT_SUPP 0
-+#define EXT2_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
- #define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE
- #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
-@@ -624,8 +601,10 @@
-
- /* namei.c */
- extern struct inode_operations ext2_dir_inode_operations;
-+extern struct inode_operations ext2_special_inode_operations;
-
- /* symlink.c */
-+extern struct inode_operations ext2_symlink_inode_operations;
- extern struct inode_operations ext2_fast_symlink_inode_operations;
-
- #endif /* __KERNEL__ */
-Index: linux-2.4.24-vanilla/include/linux/ext2_xattr.h
-===================================================================
---- linux-2.4.24-vanilla.orig/include/linux/ext2_xattr.h 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.24-vanilla/include/linux/ext2_xattr.h 2004-01-10 17:20:28.000000000 +0300
-@@ -0,0 +1,157 @@
-+/*
-+ File: linux/ext2_xattr.h
-+
-+ On-disk format of extended attributes for the ext2 filesystem.
-+
-+ (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+*/
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+#include <linux/xattr.h>
-+
-+/* Magic value in attribute blocks */
-+#define EXT2_XATTR_MAGIC 0xEA020000
-+
-+/* Maximum number of references to one attribute block */
-+#define EXT2_XATTR_REFCOUNT_MAX 1024
-+
-+/* Name indexes */
-+#define EXT2_XATTR_INDEX_MAX 10
-+#define EXT2_XATTR_INDEX_USER 1
-+#define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS 2
-+#define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT 3
-+
-+struct ext2_xattr_header {
-+ __u32 h_magic; /* magic number for identification */
-+ __u32 h_refcount; /* reference count */
-+ __u32 h_blocks; /* number of disk blocks used */
-+ __u32 h_hash; /* hash value of all attributes */
-+ __u32 h_reserved[4]; /* zero right now */
-+};
-+
-+struct ext2_xattr_entry {
-+ __u8 e_name_len; /* length of name */
-+ __u8 e_name_index; /* attribute name index */
-+ __u16 e_value_offs; /* offset in disk block of value */
-+ __u32 e_value_block; /* disk block attribute is stored on (n/i) */
-+ __u32 e_value_size; /* size of attribute value */
-+ __u32 e_hash; /* hash value of name and value */
-+ char e_name[0]; /* attribute name */
-+};
-+
-+#define EXT2_XATTR_PAD_BITS 2
-+#define EXT2_XATTR_PAD (1<<EXT2_XATTR_PAD_BITS)
-+#define EXT2_XATTR_ROUND (EXT2_XATTR_PAD-1)
-+#define EXT2_XATTR_LEN(name_len) \
-+ (((name_len) + EXT2_XATTR_ROUND + \
-+ sizeof(struct ext2_xattr_entry)) & ~EXT2_XATTR_ROUND)
-+#define EXT2_XATTR_NEXT(entry) \
-+ ( (struct ext2_xattr_entry *)( \
-+ (char *)(entry) + EXT2_XATTR_LEN((entry)->e_name_len)) )
-+#define EXT2_XATTR_SIZE(size) \
-+ (((size) + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND)
-+
-+#ifdef __KERNEL__
-+
-+# ifdef CONFIG_EXT2_FS_XATTR
-+
-+struct ext2_xattr_handler {
-+ char *prefix;
-+ size_t (*list)(char *list, struct inode *inode, const char *name,
-+ int name_len);
-+ int (*get)(struct inode *inode, const char *name, void *buffer,
-+ size_t size);
-+ int (*set)(struct inode *inode, const char *name, const void *buffer,
-+ size_t size, int flags);
-+};
-+
-+extern int ext2_xattr_register(int, struct ext2_xattr_handler *);
-+extern void ext2_xattr_unregister(int, struct ext2_xattr_handler *);
-+
-+extern int ext2_setxattr(struct dentry *, const char *, const void *, size_t, int);
-+extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t);
-+extern ssize_t ext2_listxattr(struct dentry *, char *, size_t);
-+extern int ext2_removexattr(struct dentry *, const char *);
-+
-+extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t);
-+extern int ext2_xattr_list(struct inode *, char *, size_t);
-+extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
-+
-+extern void ext2_xattr_delete_inode(struct inode *);
-+extern void ext2_xattr_put_super(struct super_block *);
-+
-+extern int init_ext2_xattr(void) __init;
-+extern void exit_ext2_xattr(void);
-+
-+# else /* CONFIG_EXT2_FS_XATTR */
-+# define ext2_setxattr NULL
-+# define ext2_getxattr NULL
-+# define ext2_listxattr NULL
-+# define ext2_removexattr NULL
-+
-+static inline int
-+ext2_xattr_get(struct inode *inode, int name_index,
-+ const char *name, void *buffer, size_t size)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline int
-+ext2_xattr_list(struct inode *inode, char *buffer, size_t size)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline int
-+ext2_xattr_set(struct inode *inode, int name_index, const char *name,
-+ const void *value, size_t size, int flags)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline void
-+ext2_xattr_delete_inode(struct inode *inode)
-+{
-+}
-+
-+static inline void
-+ext2_xattr_put_super(struct super_block *sb)
-+{
-+}
-+
-+static inline int
-+init_ext2_xattr(void)
-+{
-+ return 0;
-+}
-+
-+static inline void
-+exit_ext2_xattr(void)
-+{
-+}
-+
-+# endif /* CONFIG_EXT2_FS_XATTR */
-+
-+# ifdef CONFIG_EXT2_FS_XATTR_USER
-+
-+extern int init_ext2_xattr_user(void) __init;
-+extern void exit_ext2_xattr_user(void);
-+
-+# else /* CONFIG_EXT2_FS_XATTR_USER */
-+
-+static inline int
-+init_ext2_xattr_user(void)
-+{
-+ return 0;
-+}
-+
-+static inline void
-+exit_ext2_xattr_user(void)
-+{
-+}
-+
-+# endif /* CONFIG_EXT2_FS_XATTR_USER */
-+
-+#endif /* __KERNEL__ */
-+
-Index: linux-2.4.24-vanilla/include/linux/ext3_fs.h
-===================================================================
---- linux-2.4.24-vanilla.orig/include/linux/ext3_fs.h 2004-01-10 17:11:50.000000000 +0300
-+++ linux-2.4.24-vanilla/include/linux/ext3_fs.h 2004-01-10 17:20:28.000000000 +0300
-@@ -63,8 +63,6 @@
- */
- #define EXT3_BAD_INO 1 /* Bad blocks inode */
- #define EXT3_ROOT_INO 2 /* Root inode */
--#define EXT3_ACL_IDX_INO 3 /* ACL inode */
--#define EXT3_ACL_DATA_INO 4 /* ACL inode */
- #define EXT3_BOOT_LOADER_INO 5 /* Boot loader inode */
- #define EXT3_UNDEL_DIR_INO 6 /* Undelete directory inode */
- #define EXT3_RESIZE_INO 7 /* Reserved group descriptors inode */
-@@ -94,7 +92,6 @@
- #else
- # define EXT3_BLOCK_SIZE(s) (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)
- #endif
--#define EXT3_ACLE_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_acl_entry))
- #define EXT3_ADDR_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (__u32))
- #ifdef __KERNEL__
- # define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
-@@ -129,28 +126,6 @@
- #endif
-
- /*
-- * ACL structures
-- */
--struct ext3_acl_header /* Header of Access Control Lists */
--{
-- __u32 aclh_size;
-- __u32 aclh_file_count;
-- __u32 aclh_acle_count;
-- __u32 aclh_first_acle;
--};
--
--struct ext3_acl_entry /* Access Control List Entry */
--{
-- __u32 acle_size;
-- __u16 acle_perms; /* Access permissions */
-- __u16 acle_type; /* Type of entry */
-- __u16 acle_tag; /* User or group identity */
-- __u16 acle_pad1;
-- __u32 acle_next; /* Pointer on next entry for the */
-- /* same inode or on next free entry */
--};
--
--/*
- * Structure of a blocks group descriptor
- */
- struct ext3_group_desc
-@@ -344,6 +319,7 @@
- #define EXT3_MOUNT_WRITEBACK_DATA 0x0C00 /* No data ordering */
- #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */
- #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */
-+#define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
-
- /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
- #ifndef _LINUX_EXT2_FS_H
-@@ -521,7 +497,7 @@
- #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
- #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
-
--#define EXT3_FEATURE_COMPAT_SUPP 0
-+#define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR
- #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \
- EXT3_FEATURE_INCOMPAT_RECOVER)
- #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
-@@ -704,6 +680,7 @@
- extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
-
- /* inode.c */
-+extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
- extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
- extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
-
-@@ -773,8 +750,10 @@
-
- /* namei.c */
- extern struct inode_operations ext3_dir_inode_operations;
-+extern struct inode_operations ext3_special_inode_operations;
-
- /* symlink.c */
-+extern struct inode_operations ext3_symlink_inode_operations;
- extern struct inode_operations ext3_fast_symlink_inode_operations;
-
-
-Index: linux-2.4.24-vanilla/include/linux/ext3_jbd.h
-===================================================================
---- linux-2.4.24-vanilla.orig/include/linux/ext3_jbd.h 2004-01-10 17:11:50.000000000 +0300
-+++ linux-2.4.24-vanilla/include/linux/ext3_jbd.h 2004-01-10 17:20:28.000000000 +0300
-@@ -30,13 +30,19 @@
-
- #define EXT3_SINGLEDATA_TRANS_BLOCKS 8U
-
-+/* Extended attributes may touch two data buffers, two bitmap buffers,
-+ * and two group and summaries. */
-+
-+#define EXT3_XATTR_TRANS_BLOCKS 8
-+
- /* Define the minimum size for a transaction which modifies data. This
- * needs to take into account the fact that we may end up modifying two
- * quota files too (one for the group, one for the user quota). The
- * superblock only gets updated once, of course, so don't bother
- * counting that again for the quota updates. */
-
--#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS - 2)
-+#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS + \
-+ EXT3_XATTR_TRANS_BLOCKS - 2)
-
- extern int ext3_writepage_trans_blocks(struct inode *inode);
-
-Index: linux-2.4.24-vanilla/include/linux/ext3_xattr.h
-===================================================================
---- linux-2.4.24-vanilla.orig/include/linux/ext3_xattr.h 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.24-vanilla/include/linux/ext3_xattr.h 2004-01-10 17:20:28.000000000 +0300
-@@ -0,0 +1,157 @@
-+/*
-+ File: linux/ext3_xattr.h
-+
-+ On-disk format of extended attributes for the ext3 filesystem.
-+
-+ (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+*/
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+#include <linux/xattr.h>
-+
-+/* Magic value in attribute blocks */
-+#define EXT3_XATTR_MAGIC 0xEA020000
-+
-+/* Maximum number of references to one attribute block */
-+#define EXT3_XATTR_REFCOUNT_MAX 1024
-+
-+/* Name indexes */
-+#define EXT3_XATTR_INDEX_MAX 10
-+#define EXT3_XATTR_INDEX_USER 1
-+#define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS 2
-+#define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT 3
-+
-+struct ext3_xattr_header {
-+ __u32 h_magic; /* magic number for identification */
-+ __u32 h_refcount; /* reference count */
-+ __u32 h_blocks; /* number of disk blocks used */
-+ __u32 h_hash; /* hash value of all attributes */
-+ __u32 h_reserved[4]; /* zero right now */
-+};
-+
-+struct ext3_xattr_entry {
-+ __u8 e_name_len; /* length of name */
-+ __u8 e_name_index; /* attribute name index */
-+ __u16 e_value_offs; /* offset in disk block of value */
-+ __u32 e_value_block; /* disk block attribute is stored on (n/i) */
-+ __u32 e_value_size; /* size of attribute value */
-+ __u32 e_hash; /* hash value of name and value */
-+ char e_name[0]; /* attribute name */
-+};
-+
-+#define EXT3_XATTR_PAD_BITS 2
-+#define EXT3_XATTR_PAD (1<<EXT3_XATTR_PAD_BITS)
-+#define EXT3_XATTR_ROUND (EXT3_XATTR_PAD-1)
-+#define EXT3_XATTR_LEN(name_len) \
-+ (((name_len) + EXT3_XATTR_ROUND + \
-+ sizeof(struct ext3_xattr_entry)) & ~EXT3_XATTR_ROUND)
-+#define EXT3_XATTR_NEXT(entry) \
-+ ( (struct ext3_xattr_entry *)( \
-+ (char *)(entry) + EXT3_XATTR_LEN((entry)->e_name_len)) )
-+#define EXT3_XATTR_SIZE(size) \
-+ (((size) + EXT3_XATTR_ROUND) & ~EXT3_XATTR_ROUND)
-+
-+#ifdef __KERNEL__
-+
-+# ifdef CONFIG_EXT3_FS_XATTR
-+
-+struct ext3_xattr_handler {
-+ char *prefix;
-+ size_t (*list)(char *list, struct inode *inode, const char *name,
-+ int name_len);
-+ int (*get)(struct inode *inode, const char *name, void *buffer,
-+ size_t size);
-+ int (*set)(struct inode *inode, const char *name, const void *buffer,
-+ size_t size, int flags);
-+};
-+
-+extern int ext3_xattr_register(int, struct ext3_xattr_handler *);
-+extern void ext3_xattr_unregister(int, struct ext3_xattr_handler *);
-+
-+extern int ext3_setxattr(struct dentry *, const char *, const void *, size_t, int);
-+extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t);
-+extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
-+extern int ext3_removexattr(struct dentry *, const char *);
-+
-+extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
-+extern int ext3_xattr_list(struct inode *, char *, size_t);
-+extern int ext3_xattr_set(handle_t *handle, struct inode *, int, const char *, const void *, size_t, int);
-+
-+extern void ext3_xattr_delete_inode(handle_t *, struct inode *);
-+extern void ext3_xattr_put_super(struct super_block *);
-+
-+extern int init_ext3_xattr(void) __init;
-+extern void exit_ext3_xattr(void);
-+
-+# else /* CONFIG_EXT3_FS_XATTR */
-+# define ext3_setxattr NULL
-+# define ext3_getxattr NULL
-+# define ext3_listxattr NULL
-+# define ext3_removexattr NULL
-+
-+static inline int
-+ext3_xattr_get(struct inode *inode, int name_index, const char *name,
-+ void *buffer, size_t size)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline int
-+ext3_xattr_list(struct inode *inode, void *buffer, size_t size)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline int
-+ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
-+ const char *name, const void *value, size_t size, int flags)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline void
-+ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
-+{
-+}
-+
-+static inline void
-+ext3_xattr_put_super(struct super_block *sb)
-+{
-+}
-+
-+static inline int
-+init_ext3_xattr(void)
-+{
-+ return 0;
-+}
-+
-+static inline void
-+exit_ext3_xattr(void)
-+{
-+}
-+
-+# endif /* CONFIG_EXT3_FS_XATTR */
-+
-+# ifdef CONFIG_EXT3_FS_XATTR_USER
-+
-+extern int init_ext3_xattr_user(void) __init;
-+extern void exit_ext3_xattr_user(void);
-+
-+# else /* CONFIG_EXT3_FS_XATTR_USER */
-+
-+static inline int
-+init_ext3_xattr_user(void)
-+{
-+ return 0;
-+}
-+
-+static inline void
-+exit_ext3_xattr_user(void)
-+{
-+}
-+
-+#endif /* CONFIG_EXT3_FS_XATTR_USER */
-+
-+#endif /* __KERNEL__ */
-+
-Index: linux-2.4.24-vanilla/include/linux/fs.h
-===================================================================
---- linux-2.4.24-vanilla.orig/include/linux/fs.h 2004-01-10 17:11:45.000000000 +0300
-+++ linux-2.4.24-vanilla/include/linux/fs.h 2004-01-10 17:20:28.000000000 +0300
-@@ -913,7 +913,7 @@
- int (*setattr) (struct dentry *, struct iattr *);
- int (*setattr_raw) (struct inode *, struct iattr *);
- int (*getattr) (struct dentry *, struct iattr *);
-- int (*setxattr) (struct dentry *, const char *, void *, size_t, int);
-+ int (*setxattr) (struct dentry *, const char *, const void *, size_t, int);
- ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
- ssize_t (*listxattr) (struct dentry *, char *, size_t);
- int (*removexattr) (struct dentry *, const char *);
-Index: linux-2.4.24-vanilla/include/linux/mbcache.h
-===================================================================
---- linux-2.4.24-vanilla.orig/include/linux/mbcache.h 2003-01-30 13:24:37.000000000 +0300
-+++ linux-2.4.24-vanilla/include/linux/mbcache.h 2004-01-10 17:20:28.000000000 +0300
-@@ -0,0 +1,69 @@
-+/*
-+ File: linux/mbcache.h
-+
-+ (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+*/
-+
-+/* Hardwire the number of additional indexes */
-+#define MB_CACHE_INDEXES_COUNT 1
-+
-+struct mb_cache_entry;
-+
-+struct mb_cache_op {
-+ int (*free)(struct mb_cache_entry *, int);
-+};
-+
-+struct mb_cache {
-+ struct list_head c_cache_list;
-+ const char *c_name;
-+ struct mb_cache_op c_op;
-+ atomic_t c_entry_count;
-+ int c_bucket_count;
-+#ifndef MB_CACHE_INDEXES_COUNT
-+ int c_indexes_count;
-+#endif
-+ kmem_cache_t *c_entry_cache;
-+ struct list_head *c_block_hash;
-+ struct list_head *c_indexes_hash[0];
-+};
-+
-+struct mb_cache_entry_index {
-+ struct list_head o_list;
-+ unsigned int o_key;
-+};
-+
-+struct mb_cache_entry {
-+ struct list_head e_lru_list;
-+ struct mb_cache *e_cache;
-+ atomic_t e_used;
-+ kdev_t e_dev;
-+ unsigned long e_block;
-+ struct list_head e_block_list;
-+ struct mb_cache_entry_index e_indexes[0];
-+};
-+
-+/* Functions on caches */
-+
-+struct mb_cache * mb_cache_create(const char *, struct mb_cache_op *, size_t,
-+ int, int);
-+void mb_cache_shrink(struct mb_cache *, kdev_t);
-+void mb_cache_destroy(struct mb_cache *);
-+
-+/* Functions on cache entries */
-+
-+struct mb_cache_entry *mb_cache_entry_alloc(struct mb_cache *);
-+int mb_cache_entry_insert(struct mb_cache_entry *, kdev_t, unsigned long,
-+ unsigned int[]);
-+void mb_cache_entry_rehash(struct mb_cache_entry *, unsigned int[]);
-+void mb_cache_entry_release(struct mb_cache_entry *);
-+void mb_cache_entry_takeout(struct mb_cache_entry *);
-+void mb_cache_entry_free(struct mb_cache_entry *);
-+struct mb_cache_entry *mb_cache_entry_dup(struct mb_cache_entry *);
-+struct mb_cache_entry *mb_cache_entry_get(struct mb_cache *, kdev_t,
-+ unsigned long);
-+#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0)
-+struct mb_cache_entry *mb_cache_entry_find_first(struct mb_cache *cache, int,
-+ kdev_t, unsigned int);
-+struct mb_cache_entry *mb_cache_entry_find_next(struct mb_cache_entry *, int,
-+ kdev_t, unsigned int);
-+#endif
-Index: linux-2.4.24-vanilla/kernel/ksyms.c
-===================================================================
---- linux-2.4.24-vanilla.orig/kernel/ksyms.c 2004-01-10 17:11:43.000000000 +0300
-+++ linux-2.4.24-vanilla/kernel/ksyms.c 2004-01-10 17:20:28.000000000 +0300
-@@ -11,6 +11,7 @@
-
- #include <linux/config.h>
- #include <linux/slab.h>
-+#include <linux/cache_def.h>
- #include <linux/module.h>
- #include <linux/blkdev.h>
- #include <linux/cdrom.h>
-@@ -92,6 +93,7 @@
- EXPORT_SYMBOL(exit_files);
- EXPORT_SYMBOL(exit_fs);
- EXPORT_SYMBOL(exit_sighand);
-+EXPORT_SYMBOL(copy_fs_struct);
-
- /* internal kernel memory management */
- EXPORT_SYMBOL(_alloc_pages);
-@@ -109,6 +111,8 @@
- EXPORT_SYMBOL(kmem_cache_alloc);
- EXPORT_SYMBOL(kmem_cache_free);
- EXPORT_SYMBOL(kmem_cache_size);
-+EXPORT_SYMBOL(register_cache);
-+EXPORT_SYMBOL(unregister_cache);
- EXPORT_SYMBOL(kmalloc);
- EXPORT_SYMBOL(kfree);
- EXPORT_SYMBOL(vfree);
-Index: linux-2.4.24-vanilla/mm/vmscan.c
-===================================================================
---- linux-2.4.24-vanilla.orig/mm/vmscan.c 2004-01-10 17:06:00.000000000 +0300
-+++ linux-2.4.24-vanilla/mm/vmscan.c 2004-01-10 17:21:00.000000000 +0300
-@@ -18,6 +18,7 @@
- #include <linux/kernel_stat.h>
- #include <linux/swap.h>
- #include <linux/swapctl.h>
-+#include <linux/cache_def.h>
- #include <linux/smp_lock.h>
- #include <linux/pagemap.h>
- #include <linux/init.h>
-@@ -34,6 +35,39 @@
- */
- int vm_passes = 60;
-
-+static DECLARE_MUTEX(other_caches_sem);
-+static LIST_HEAD(cache_definitions);
-+
-+void register_cache(struct cache_definition *cache)
-+{
-+ down(&other_caches_sem);
-+ list_add(&cache->link, &cache_definitions);
-+ up(&other_caches_sem);
-+}
-+
-+void unregister_cache(struct cache_definition *cache)
-+{
-+ down(&other_caches_sem);
-+ list_del(&cache->link);
-+ up(&other_caches_sem);
-+}
-+
-+static void shrink_other_caches(unsigned int priority, int gfp_mask)
-+{
-+ struct list_head *p;
-+
-+ if (down_trylock(&other_caches_sem))
-+ return;
-+
-+ list_for_each_prev(p, &cache_definitions) {
-+ struct cache_definition *cache =
-+ list_entry(p, struct cache_definition, link);
-+
-+ cache->shrink(priority, gfp_mask);
-+ }
-+ up(&other_caches_sem);
-+}
-+
- /*
- * "vm_cache_scan_ratio" is how much of the inactive LRU queue we will scan
- * in one go. A value of 6 for vm_cache_scan_ratio implies that we'll
-@@ -523,6 +557,7 @@
- #ifdef CONFIG_QUOTA
- shrink_dqcache_memory(vm_vfs_scan_ratio, gfp_mask);
- #endif
-+ shrink_other_caches(vm_vfs_scan_ratio, gfp_mask);
-
- if (!*failed_swapout)
- *failed_swapout = !swap_out(classzone);
-@@ -645,6 +680,7 @@
- #ifdef CONFIG_QUOTA
- shrink_dqcache_memory(vm_vfs_scan_ratio, gfp_mask);
- #endif
-+ shrink_other_caches(vm_vfs_scan_ratio, gfp_mask);
- if (!failed_swapout)
- failed_swapout = !swap_out(classzone);
- } while (--tries);
+++ /dev/null
-Index: linux-2.4.20/include/linux/list.h
-===================================================================
---- linux-2.4.20.orig/include/linux/list.h 2003-10-17 23:56:26.000000000 +0400
-+++ linux-2.4.20/include/linux/list.h 2003-10-22 14:02:22.000000000 +0400
-@@ -227,6 +227,17 @@
- pos = list_entry(pos->member.next, typeof(*pos), member), \
- prefetch(pos->member.next))
-
-+/* 2.5 uses hlists for some things, like the d_hash. we'll treat them
-+ * as 2.5 and let macros drop back.. */
-+#define hlist_entry list_entry
-+#define hlist_head list_head
-+#define hlist_node list_head
-+#define HLIST_HEAD LIST_HEAD
-+#define INIT_HLIST_HEAD INIT_LIST_HEAD
-+#define hlist_del_init list_del_init
-+#define hlist_add_head list_add
-+#define hlist_for_each_safe list_for_each_safe
-+
- #endif /* __KERNEL__ || _LVM_H_INCLUDE */
-
- #endif
+++ /dev/null
-Index: linux-2.4.24/drivers/net/netconsole.c
-===================================================================
---- linux-2.4.24.orig/drivers/net/netconsole.c 2003-01-30 18:24:37.000000000 +0800
-+++ linux-2.4.24/drivers/net/netconsole.c 2004-06-09 18:53:37.000000000 +0800
-@@ -0,0 +1,1376 @@
-+/*
-+ * linux/drivers/net/netconsole.c
-+ *
-+ * Copyright (C) 2001 Ingo Molnar <mingo@redhat.com>
-+ * Copyright (C) 2002 Red Hat, Inc.
-+ *
-+ * This file contains the implementation of an IRQ-safe, crash-safe
-+ * kernel console implementation that outputs kernel messages to the
-+ * network.
-+ *
-+ * Modification history:
-+ *
-+ * 2001-09-17 started by Ingo Molnar.
-+ * 2002-03-14 simultaneous syslog packet option by Michael K. Johnson
-+ * 2003-10-30 Add sysrq command processing by Wangdi <wangdi@clusterfs.com>
-+ *
-+ */
-+
-+/****************************************************************
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ ****************************************************************/
-+
-+#include <net/tcp.h>
-+#include <net/udp.h>
-+#include <linux/mm.h>
-+#include <linux/tty.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/random.h>
-+#include <linux/reboot.h>
-+#include <linux/module.h>
-+#include <asm/unaligned.h>
-+#include <asm/pgtable.h>
-+#if CONFIG_X86_LOCAL_APIC
-+#include <asm/apic.h>
-+#endif
-+#include <linux/console.h>
-+#include <linux/smp_lock.h>
-+#include <linux/netdevice.h>
-+#include <linux/tty_driver.h>
-+#include <linux/etherdevice.h>
-+#include <linux/elf.h>
-+#include <linux/sysrq.h>
-+#include "netconsole.h"
-+
-+static struct net_device *netconsole_dev;
-+static u16 source_port, netdump_target_port, netlog_target_port, syslog_target_port;
-+static u32 source_ip, netdump_target_ip, netlog_target_ip, syslog_target_ip;
-+static unsigned char netdump_daddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} ;
-+static unsigned char netlog_daddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} ;
-+static unsigned char syslog_daddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} ;
-+
-+static unsigned int mhz = 500, idle_timeout;
-+static unsigned long long mhz_cycles, jiffy_cycles;
-+
-+
-+#define MAX_UDP_CHUNK 1460
-+#define MAX_PRINT_CHUNK (MAX_UDP_CHUNK-HEADER_LEN)
-+
-+#define DEBUG 0
-+#if DEBUG
-+# define Dprintk(x...) printk(KERN_INFO x)
-+#else
-+# define Dprintk(x...)
-+#endif
-+/*
-+ * We maintain a small pool of fully-sized skbs,
-+ * to make sure the message gets out even in
-+ * extreme OOM situations.
-+ */
-+#define MAX_NETCONSOLE_SKBS 128
-+
-+static spinlock_t netconsole_lock = SPIN_LOCK_UNLOCKED;
-+static int nr_netconsole_skbs;
-+static struct sk_buff *netconsole_skbs;
-+
-+#define MAX_SKB_SIZE \
-+ (MAX_UDP_CHUNK + sizeof(struct udphdr) + \
-+ sizeof(struct iphdr) + sizeof(struct ethhdr))
-+
-+static int new_arp = 0;
-+static unsigned char arp_sha[ETH_ALEN], arp_tha[ETH_ALEN];
-+static u32 arp_sip, arp_tip;
-+
-+static void send_netconsole_arp(struct net_device *dev);
-+
-+static void __refill_netconsole_skbs(void)
-+{
-+ struct sk_buff *skb;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&netconsole_lock, flags);
-+ while (nr_netconsole_skbs < MAX_NETCONSOLE_SKBS) {
-+ skb = alloc_skb(MAX_SKB_SIZE, GFP_ATOMIC);
-+ if (!skb)
-+ break;
-+ if (netconsole_skbs)
-+ skb->next = netconsole_skbs;
-+ else
-+ skb->next = NULL;
-+ netconsole_skbs = skb;
-+ nr_netconsole_skbs++;
-+ }
-+ spin_unlock_irqrestore(&netconsole_lock, flags);
-+}
-+
-+static struct sk_buff * get_netconsole_skb(void)
-+{
-+ struct sk_buff *skb;
-+
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&netconsole_lock, flags);
-+ skb = netconsole_skbs;
-+ if (skb) {
-+ netconsole_skbs = skb->next;
-+ skb->next = NULL;
-+ nr_netconsole_skbs--;
-+ }
-+ spin_unlock_irqrestore(&netconsole_lock, flags);
-+
-+ return skb;
-+}
-+
-+static unsigned long long t0;
-+
-+/*
-+ * Do cleanups:
-+ * - zap completed output skbs.
-+ * - send ARPs if requested
-+ * - reboot the box if inactive for more than N seconds.
-+ */
-+static void zap_completion_queue(void)
-+{
-+ unsigned long long t1;
-+ int cpu = smp_processor_id();
-+
-+ if (softnet_data[cpu].completion_queue) {
-+ struct sk_buff *clist;
-+
-+ local_irq_disable();
-+ clist = softnet_data[cpu].completion_queue;
-+ softnet_data[cpu].completion_queue = NULL;
-+ local_irq_enable();
-+
-+ while (clist != NULL) {
-+ struct sk_buff *skb = clist;
-+ clist = clist->next;
-+ __kfree_skb(skb);
-+ }
-+ }
-+
-+ if (new_arp) {
-+ Dprintk("got ARP req - sending reply.\n");
-+ new_arp = 0;
-+ send_netconsole_arp(netconsole_dev);
-+ }
-+
-+ rdtscll(t1);
-+ if (idle_timeout) {
-+ if (t0) {
-+ if (((t1 - t0) >> 20) > mhz_cycles * (unsigned long long)idle_timeout) {
-+ t0 = t1;
-+ printk("netdump idle timeout - rebooting in 3 seconds.\n");
-+ mdelay(3000);
-+ machine_restart(NULL);
-+ }
-+ }
-+ }
-+ /* maintain jiffies in a polling fashion, based on rdtsc. */
-+ {
-+ static unsigned long long prev_tick;
-+
-+ if (t1 - prev_tick >= jiffy_cycles) {
-+ prev_tick += jiffy_cycles;
-+ jiffies++;
-+ }
-+ }
-+}
-+void (*irqfunc)(int, void *, struct pt_regs *);
-+
-+static void netdump_poll(struct net_device *dev)
-+{
-+ int budget = 1;
-+
-+ disable_irq(dev->irq);
-+
-+ irqfunc(dev->irq, dev, 0);
-+
-+ if(dev->poll && test_bit(__LINK_STATE_RX_SCHED, &dev->state))
-+ dev->poll(dev, &budget);
-+
-+ enable_irq(dev->irq);
-+
-+}
-+
-+static struct sk_buff * alloc_netconsole_skb(struct net_device *dev, int len, int reserve)
-+{
-+ int once = 1;
-+ int count = 0;
-+ struct sk_buff *skb = NULL;
-+
-+repeat:
-+ zap_completion_queue();
-+ if (nr_netconsole_skbs < MAX_NETCONSOLE_SKBS)
-+ __refill_netconsole_skbs();
-+
-+ skb = alloc_skb(len, GFP_ATOMIC);
-+ if (!skb) {
-+ skb = get_netconsole_skb();
-+ if (!skb) {
-+ count++;
-+ if (once && (count == 1000000)) {
-+ printk("possibly FATAL: out of netconsole skbs!!! will keep retrying.\n");
-+ once = 0;
-+ }
-+ Dprintk("alloc skb: polling controller ...\n");
-+ netdump_poll(dev);
-+ goto repeat;
-+ }
-+ }
-+
-+ atomic_set(&skb->users, 1);
-+ skb_reserve(skb, reserve);
-+ return skb;
-+}
-+
-+static void transmit_raw_skb(struct sk_buff *skb, struct net_device *dev)
-+{
-+
-+repeat_poll:
-+ spin_lock(&dev->xmit_lock);
-+ dev->xmit_lock_owner = smp_processor_id();
-+
-+ if (netif_queue_stopped(dev)) {
-+ dev->xmit_lock_owner = -1;
-+ spin_unlock(&dev->xmit_lock);
-+
-+ Dprintk("xmit skb: polling controller ...\n");
-+ netdump_poll(dev);
-+ zap_completion_queue();
-+ goto repeat_poll;
-+ }
-+
-+ dev->hard_start_xmit(skb, dev);
-+
-+ dev->xmit_lock_owner = -1;
-+ spin_unlock(&dev->xmit_lock);
-+}
-+
-+static void transmit_netconsole_skb(struct sk_buff *skb, struct net_device *dev,
-+ int ip_len, int udp_len,
-+ u16 source_port, u16 target_port, u32 source_ip, u32 target_ip,
-+ unsigned char * macdaddr)
-+{
-+ struct udphdr *udph;
-+ struct iphdr *iph;
-+ struct ethhdr *eth;
-+
-+ udph = (struct udphdr *) skb_push(skb, sizeof(*udph));
-+ udph->source = source_port;
-+ udph->dest = target_port;
-+ udph->len = htons(udp_len);
-+ udph->check = 0;
-+
-+ iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
-+
-+ iph->version = 4;
-+ iph->ihl = 5;
-+ iph->tos = 0;
-+ iph->tot_len = htons(ip_len);
-+ iph->id = 0;
-+ iph->frag_off = 0;
-+ iph->ttl = 64;
-+ iph->protocol = IPPROTO_UDP;
-+ iph->check = 0;
-+ iph->saddr = source_ip;
-+ iph->daddr = target_ip;
-+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
-+
-+ eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
-+
-+ eth->h_proto = htons(ETH_P_IP);
-+ memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
-+ memcpy(eth->h_dest, macdaddr, dev->addr_len);
-+
-+ transmit_raw_skb(skb, dev);
-+}
-+
-+static void send_netconsole_arp(struct net_device *dev)
-+{
-+ int total_len, arp_len, arp_data_len;
-+ struct sk_buff *skb;
-+ unsigned char *arp;
-+ struct arphdr *arph;
-+ struct ethhdr *eth;
-+
-+ arp_data_len = 2*4 + 2*ETH_ALEN;
-+ arp_len = arp_data_len + sizeof(struct arphdr);
-+ total_len = arp_len + ETH_HLEN;
-+
-+ skb = alloc_netconsole_skb(dev, total_len, total_len - arp_data_len);
-+
-+ arp = skb->data;
-+
-+ memcpy(arp, dev->dev_addr, ETH_ALEN);
-+ arp += ETH_ALEN;
-+
-+ memcpy(arp, &source_ip, 4);
-+ arp += 4;
-+
-+ memcpy(arp, arp_sha, ETH_ALEN);
-+ arp += ETH_ALEN;
-+
-+ memcpy(arp, &arp_sip, 4);
-+ arp += 4;
-+
-+ skb->len += 2*4 + 2*ETH_ALEN;
-+
-+ arph = (struct arphdr *)skb_push(skb, sizeof(*arph));
-+
-+ arph->ar_hrd = htons(dev->type);
-+ arph->ar_pro = __constant_htons(ETH_P_IP);
-+ arph->ar_hln = ETH_ALEN;
-+ arph->ar_pln = 4;
-+ arph->ar_op = __constant_htons(ARPOP_REPLY);
-+
-+ eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
-+
-+ eth->h_proto = htons(ETH_P_ARP);
-+ memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
-+ memcpy(eth->h_dest, arp_sha, dev->addr_len);
-+
-+ transmit_raw_skb(skb, dev);
-+}
-+
-+static void send_netdump_skb(struct net_device *dev, const char *msg, unsigned int msg_len, reply_t *reply)
-+{
-+ int total_len, ip_len, udp_len;
-+ struct sk_buff *skb;
-+
-+ udp_len = msg_len + HEADER_LEN + sizeof(struct udphdr);
-+ ip_len = udp_len + sizeof(struct iphdr);
-+ total_len = ip_len + ETH_HLEN;
-+
-+ skb = alloc_netconsole_skb(dev, total_len, total_len - msg_len - HEADER_LEN);
-+
-+ skb->data[0] = NETCONSOLE_VERSION;
-+ put_unaligned(htonl(reply->nr), (u32 *) (skb->data + 1));
-+ put_unaligned(htonl(reply->code), (u32 *) (skb->data + 5));
-+ put_unaligned(htonl(reply->info), (u32 *) (skb->data + 9));
-+
-+ memcpy(skb->data + HEADER_LEN, msg, msg_len);
-+ skb->len += msg_len + HEADER_LEN;
-+
-+ transmit_netconsole_skb(skb, dev, ip_len, udp_len,
-+ source_port, netdump_target_port, source_ip, netdump_target_ip, netdump_daddr);
-+}
-+
-+#define SYSLOG_HEADER_LEN 4
-+
-+static void send_netlog_skb(struct net_device *dev, const char *msg, unsigned int msg_len, reply_t *reply)
-+{
-+ int total_len, ip_len, udp_len;
-+ struct sk_buff *skb;
-+
-+ udp_len = msg_len + HEADER_LEN + sizeof(struct udphdr);
-+ ip_len = udp_len + sizeof(struct iphdr);
-+ total_len = ip_len + ETH_HLEN;
-+
-+ skb = alloc_netconsole_skb(dev, total_len, total_len - msg_len - HEADER_LEN);
-+
-+ skb->data[0] = NETCONSOLE_VERSION;
-+ put_unaligned(htonl(reply->nr), (u32 *) (skb->data + 1));
-+ put_unaligned(htonl(reply->code), (u32 *) (skb->data + 5));
-+ put_unaligned(htonl(reply->info), (u32 *) (skb->data + 9));
-+
-+ memcpy(skb->data + HEADER_LEN, msg, msg_len);
-+ skb->len += msg_len + HEADER_LEN;
-+
-+ transmit_netconsole_skb(skb, dev, ip_len, udp_len,
-+ source_port, netlog_target_port, source_ip, netlog_target_ip, netlog_daddr);
-+}
-+
-+#define SYSLOG_HEADER_LEN 4
-+
-+static void send_syslog_skb(struct net_device *dev, const char *msg, unsigned int msg_len, int pri)
-+{
-+ int total_len, ip_len, udp_len;
-+ struct sk_buff *skb;
-+
-+ udp_len = msg_len + SYSLOG_HEADER_LEN + sizeof(struct udphdr);
-+ ip_len = udp_len + sizeof(struct iphdr);
-+ total_len = ip_len + ETH_HLEN;
-+
-+ skb = alloc_netconsole_skb(dev, total_len, total_len - msg_len - SYSLOG_HEADER_LEN);
-+
-+ skb->data[0] = '<';
-+ skb->data[1] = pri + '0';
-+ skb->data[2]= '>';
-+ skb->data[3]= ' ';
-+
-+ memcpy(skb->data + SYSLOG_HEADER_LEN, msg, msg_len);
-+ skb->len += msg_len + SYSLOG_HEADER_LEN;
-+
-+ transmit_netconsole_skb(skb, dev, ip_len, udp_len, source_port,
-+ syslog_target_port, source_ip, syslog_target_ip, syslog_daddr);
-+}
-+
-+#define MAX_SYSLOG_CHARS 1000
-+
-+static spinlock_t syslog_lock = SPIN_LOCK_UNLOCKED;
-+static int syslog_chars;
-+static unsigned char syslog_line [MAX_SYSLOG_CHARS + 10];
-+
-+/*
-+ * We feed kernel messages char by char, and send the UDP packet
-+ * one linefeed. We buffer all characters received.
-+ */
-+static inline void feed_syslog_char(struct net_device *dev, const unsigned char c)
-+{
-+ if (syslog_chars == MAX_SYSLOG_CHARS)
-+ syslog_chars--;
-+ syslog_line[syslog_chars] = c;
-+ syslog_chars++;
-+ if (c == '\n') {
-+ send_syslog_skb(dev, syslog_line, syslog_chars, 5);
-+ syslog_chars = 0;
-+ }
-+}
-+
-+static spinlock_t sequence_lock = SPIN_LOCK_UNLOCKED;
-+static unsigned int log_offset;
-+
-+static int thread_stopped = 0;
-+/*Interrupt function for netdump */
-+static int sysrq_mode = 0;
-+static int stop_sysrq_thread = 0;
-+#define Set_Sysrq_mode() (sysrq_mode = 1)
-+#define Clear_Sysrq_mode() (sysrq_mode = 0)
-+static char send_cache[MAX_PRINT_CHUNK];
-+static unsigned int send_cache_pos = 0;
-+wait_queue_head_t sysrq_thread_queue;
-+wait_queue_head_t sysrq_thread_waiter_queue;
-+
-+#define SEND_MSG_BUFFER(buf, len) \
-+do \
-+{ \
-+ reply_t reply; \
-+ unsigned int flags; \
-+ __save_flags(flags); \
-+ __cli(); \
-+ reply.code = REPLY_LOG; \
-+ reply.nr = 0; \
-+ reply.info = 0; \
-+ spin_lock(&sequence_lock); \
-+ send_netlog_skb(dev, buf, len, &reply); \
-+ spin_unlock(&sequence_lock); \
-+ __restore_flags(flags); \
-+}while(0);
-+
-+void netconsole_do_sysrq(req_t *req)
-+{
-+ struct pt_regs regs;
-+ struct net_device *dev = netconsole_dev;
-+
-+ if (!dev)
-+ return;
-+ Set_Sysrq_mode();
-+ get_current_regs(®s);
-+ handle_sysrq((int)req->from, ®s, NULL, NULL);
-+ Dprintk("Do the command netconsole\n");
-+ if (send_cache_pos != 0){
-+ SEND_MSG_BUFFER(send_cache, send_cache_pos);
-+ memset(send_cache, 0, MAX_PRINT_CHUNK);
-+ send_cache_pos = 0;
-+ }
-+
-+ Clear_Sysrq_mode();
-+}
-+static void write_netconsole_msg(struct console *con, const char *msg0, unsigned int msg_len)
-+{
-+ int len, left, i;
-+ struct net_device *dev;
-+ const char *msg = msg0;
-+ reply_t reply;
-+
-+ dev = netconsole_dev;
-+ if (!dev || netdump_mode)
-+ return;
-+ if (sysrq_mode){
-+ unsigned long total_len = send_cache_pos + msg_len;
-+ unsigned long left_len = msg_len;
-+ while (total_len >= MAX_PRINT_CHUNK){
-+ unsigned long send_len = MAX_PRINT_CHUNK - send_cache_pos;
-+ memcpy(send_cache + send_cache_pos, msg, send_len);
-+ SEND_MSG_BUFFER(send_cache, MAX_PRINT_CHUNK);
-+ send_cache_pos = 0;
-+ total_len -= MAX_PRINT_CHUNK;
-+ left_len -= send_len;
-+ }
-+ if (left_len > 0){
-+ memcpy(send_cache + send_cache_pos, msg + (msg_len -left_len), left_len);
-+ send_cache_pos += left_len;
-+ }
-+ return;
-+ }else if (netif_running(dev)) {
-+ unsigned long flags;
-+
-+ __save_flags(flags);
-+ __cli();
-+ left = msg_len;
-+ if (netlog_target_ip) {
-+ while (left) {
-+ if (left > MAX_PRINT_CHUNK)
-+ len = MAX_PRINT_CHUNK;
-+ else
-+ len = left;
-+ reply.code = REPLY_LOG;
-+ reply.nr = 0;
-+ spin_lock(&sequence_lock);
-+ reply.info = log_offset;
-+ log_offset += len;
-+ spin_unlock(&sequence_lock);
-+ send_netlog_skb(dev, msg, len, &reply);
-+ msg += len;
-+ left -= len;
-+ }
-+ }
-+ if (syslog_target_ip) {
-+ spin_lock(&syslog_lock);
-+ for (i = 0; i < msg_len; i++)
-+ feed_syslog_char(dev, msg0[i]);
-+ spin_unlock(&syslog_lock);
-+ }
-+
-+ __restore_flags(flags);
-+ }
-+}
-+
-+static unsigned short udp_check(struct udphdr *uh, int len, unsigned long saddr, unsigned long daddr, unsigned long base)
-+{
-+ return(csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base));
-+}
-+
-+static int udp_checksum_init(struct sk_buff *skb, struct udphdr *uh,
-+ unsigned short ulen, u32 saddr, u32 daddr)
-+{
-+ if (uh->check == 0) {
-+ skb->ip_summed = CHECKSUM_UNNECESSARY;
-+ } else if (skb->ip_summed == CHECKSUM_HW) {
-+ skb->ip_summed = CHECKSUM_UNNECESSARY;
-+ if (!udp_check(uh, ulen, saddr, daddr, skb->csum))
-+ return 0;
-+ skb->ip_summed = CHECKSUM_NONE;
-+ }
-+ if (skb->ip_summed != CHECKSUM_UNNECESSARY)
-+ skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP,
-+0);
-+ /* Probably, we should checksum udp header (it should be in cache
-+ * in any case) and data in tiny packets (< rx copybreak).
-+ */
-+ return 0;
-+}
-+
-+static __inline__ int __udp_checksum_complete(struct sk_buff *skb)
-+{
-+ return (unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum));
-+}
-+
-+static __inline__ int udp_checksum_complete(struct sk_buff *skb)
-+{
-+ return skb->ip_summed != CHECKSUM_UNNECESSARY &&
-+ __udp_checksum_complete(skb);
-+}
-+
-+/*
-+ * NOTE: security depends on the trusted path between the netconsole
-+ * server and netconsole client, since none of the packets are
-+ * encrypted. The random magic number protects the protocol
-+ * against spoofing.
-+ */
-+static u64 netconsole_magic;
-+static u32 magic1, magic2;
-+
-+static spinlock_t req_lock = SPIN_LOCK_UNLOCKED;
-+static int nr_req = 0;
-+static LIST_HEAD(request_list);
-+
-+static void add_new_req(req_t *req)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&req_lock, flags);
-+ list_add_tail(&req->list, &request_list);
-+ nr_req++;
-+ Dprintk("pending requests: %d.\n", nr_req);
-+ spin_unlock_irqrestore(&req_lock, flags);
-+
-+ rdtscll(t0);
-+}
-+
-+static req_t *get_new_req(void)
-+{
-+ req_t *req = NULL;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&req_lock, flags);
-+ if (nr_req) {
-+ req = list_entry(request_list.next, req_t, list);
-+ list_del(&req->list);
-+ nr_req--;
-+ }
-+ spin_unlock_irqrestore(&req_lock, flags);
-+
-+ return req;
-+}
-+
-+static req_t *alloc_req(void)
-+{
-+ req_t *req;
-+
-+ req = (req_t *) kmalloc(sizeof(*req), GFP_ATOMIC);
-+ return req;
-+}
-+
-+static int netconsole_rx_hook(struct sk_buff *skb)
-+{
-+ int proto;
-+ struct iphdr *iph;
-+ struct udphdr *uh;
-+ __u32 len, saddr, daddr, ulen;
-+ req_t *__req;
-+ req_t *req;
-+ struct net_device *dev;
-+
-+#if DEBUG
-+ {
-+ static int packet_count;
-+ Dprintk(" %d\r", ++packet_count);
-+ }
-+#endif
-+ dev = skb->dev;
-+ if (dev->type != ARPHRD_ETHER)
-+ goto out;
-+ proto = ntohs(skb->mac.ethernet->h_proto);
-+ Dprintk("rx got skb %p (len: %d, users: %d), dev %s, h_proto: %04x.\n", skb, skb->len, atomic_read(&skb->users), dev->name, proto);
-+ #define D(x) skb->mac.ethernet->h_dest[x]
-+ Dprintk("... h_dest: %02X:%02X:%02X:%02X:%02X:%02X.\n", D(0), D(1), D(2), D(3), D(4), D(5));
-+ #undef D
-+ #define D(x) skb->mac.ethernet->h_source[x]
-+ Dprintk("... h_source: %02X:%02X:%02X:%02X:%02X:%02X.\n", D(0), D(1), D(2), D(3), D(4), D(5));
-+ #undef D
-+ if (skb->pkt_type == PACKET_OTHERHOST)
-+ goto out;
-+ if (skb_shared(skb))
-+ goto out;
-+ if (proto == ETH_P_ARP) {
-+ struct arphdr *arp;
-+ unsigned char *arp_ptr;
-+
-+ Dprintk("got arp skb.\n");
-+ arp = (struct arphdr *)skb->data;
-+ if (!pskb_may_pull(skb, sizeof(struct arphdr) + 2*4 + 2*ETH_ALEN))
-+ goto out;
-+ if (htons(dev->type) != arp->ar_hrd)
-+ goto out;
-+ if (arp->ar_pro != __constant_htons(ETH_P_IP))
-+ goto out;
-+ if (arp->ar_hln != ETH_ALEN)
-+ goto out;
-+ if (arp->ar_pln != 4)
-+ goto out;
-+ if (arp->ar_op != __constant_htons(ARPOP_REQUEST))
-+ goto out;
-+ /*
-+ * ARP header looks ok so far, extract fields:
-+ */
-+ arp_ptr = (unsigned char *)(arp + 1);
-+
-+ memcpy(arp_sha, arp_ptr, ETH_ALEN);
-+ arp_ptr += ETH_ALEN;
-+
-+ memcpy(&arp_sip, arp_ptr, 4);
-+ arp_ptr += 4;
-+
-+ memcpy(arp_tha, arp_ptr, ETH_ALEN);
-+ arp_ptr += ETH_ALEN;
-+
-+ memcpy(&arp_tip, arp_ptr, 4);
-+
-+ #define D(x) arp_sha[x]
-+ Dprintk("... arp_sha: %02X:%02X:%02X:%02X:%02X:%02X.\n", D(0), D(1), D(2), D(3), D(4), D(5));
-+ #undef D
-+ #define D(x) ((unsigned char *)&arp_sip)[x]
-+ Dprintk("... arp_sip: %d.%d.%d.%d.\n", D(0), D(1), D(2), D(3));
-+ #undef D
-+ #define D(x) arp_tha[x]
-+ Dprintk("... arp_tha: %02X:%02X:%02X:%02X:%02X:%02X.\n", D(0), D(1), D(2), D(3), D(4), D(5));
-+ #undef D
-+ #define D(x) ((unsigned char *)&arp_tip)[x]
-+ Dprintk("... arp_tip: %d.%d.%d.%d.\n", D(0), D(1), D(2), D(3));
-+ #undef D
-+ #define D(x) ((unsigned char *)&source_ip)[x]
-+ Dprintk("... (source_ip): %d.%d.%d.%d.\n", D(0), D(1), D(2), D(3));
-+ #undef D
-+
-+ if (LOOPBACK(arp_tip) || MULTICAST(arp_tip))
-+ goto out;
-+
-+ if (arp_tip != source_ip)
-+ goto out;
-+ new_arp = 1;
-+ goto out;
-+ }
-+ if (proto != ETH_P_IP)
-+ goto out;
-+ /*
-+ * IP header correctness testing:
-+ */
-+ iph = (struct iphdr *)skb->data;
-+ if (!pskb_may_pull(skb, sizeof(struct iphdr)))
-+ goto out;
-+ Dprintk("... IP ihl*4: %d, version: %d.\n", iph->ihl*4, iph->version);
-+ if (iph->ihl < 5 || iph->version != 4)
-+ goto out;
-+ if (!pskb_may_pull(skb, iph->ihl*4))
-+ goto out;
-+ if (ip_fast_csum((u8 *)iph, iph->ihl) != 0)
-+ goto out;
-+ len = ntohs(iph->tot_len);
-+ Dprintk("... IP len: %d.\n", len);
-+ if (skb->len < len || len < iph->ihl*4)
-+ goto out;
-+ saddr = iph->saddr;
-+ daddr = iph->daddr;
-+ Dprintk("... IP src: %08x, dst: %08x.\n", saddr, daddr);
-+ Dprintk("... IP protocol: %d.\n", iph->protocol);
-+ if (iph->protocol != IPPROTO_UDP)
-+ goto out;
-+ Dprintk("... netdump src: %08x, dst: %08x.\n", source_ip, netlog_target_ip);
-+ if (source_ip != daddr)
-+ goto out;
-+ if (netlog_target_ip != saddr)
-+ goto out;
-+ len -= iph->ihl*4;
-+ uh = (struct udphdr *)(((char *)iph) + iph->ihl*4);
-+ ulen = ntohs(uh->len);
-+ Dprintk("... UDP len: %d (left %d).\n", ulen, len);
-+
-+#define MIN_COMM_SIZE (sizeof(*uh) + NETDUMP_REQ_SIZE)
-+ if (ulen != len || ulen < MIN_COMM_SIZE) {
-+ Dprintk("... UDP, hm, len not ok.\n");
-+ goto out;
-+ }
-+ if (udp_checksum_init(skb, uh, ulen, saddr, daddr) < 0) {
-+ Dprintk("... UDP, hm, checksum init not ok.\n");
-+ goto out;
-+ }
-+ if (udp_checksum_complete(skb)) {
-+ Dprintk("... UDP, hm, checksum complete not ok.\n");
-+ goto out;
-+ }
-+ Dprintk("... UDP packet OK!\n");
-+ Dprintk("... UDP src port: %d, dst port: %d.\n", uh->source, uh->dest);
-+ if (source_port != uh->source)
-+ goto out;
-+ if (netlog_target_port != uh->dest)
-+ goto out;
-+ __req = (req_t *)(uh + 1);
-+ Dprintk("... UDP netdump packet OK!\n");
-+
-+ req = alloc_req();
-+ if (!req) {
-+ printk("no more RAM to allocate request - dropping it.\n");
-+ goto out;
-+ }
-+
-+ req->magic = ntohl(__req->magic);
-+ req->command = ntohl(__req->command);
-+ req->from = ntohl(__req->from);
-+ req->to = ntohl(__req->to);
-+ req->nr = ntohl(__req->nr);
-+
-+ Dprintk("... netdump magic: %08Lx.\n", req->magic);
-+ Dprintk("... netdump command: %08x.\n", req->command);
-+ Dprintk("... netdump from: %08x.\n", req->from);
-+ Dprintk("... netdump to: %08x.\n", req->to);
-+
-+ if (netdump_mode)
-+ add_new_req(req);
-+ else if (req->command == COMM_SYSRQ){
-+ add_new_req(req);
-+ wake_up(&sysrq_thread_queue);
-+ return NET_RX_DROP;
-+ }
-+out:
-+ if (!netdump_mode)
-+ return NET_RX_SUCCESS;
-+ return NET_RX_DROP;
-+}
-+
-+#define INVALID_PAGE "page is not valid!\n"
-+
-+static void send_netdump_mem (struct net_device *dev, req_t *req)
-+{
-+ int i;
-+ char *kaddr;
-+ char str[1024];
-+ struct page *page;
-+ unsigned long nr = req->from;
-+ int nr_chunks = PAGE_SIZE/1024;
-+ reply_t reply;
-+
-+ return ;
-+
-+ reply.nr = req->nr;
-+ reply.info = 0;
-+ if (req->from >= max_mapnr) {
-+ sprintf(str, "page %08lx is bigger than max page # %08lx!\n", nr, max_mapnr);
-+ reply.code = REPLY_ERROR;
-+ send_netdump_skb(dev, str, strlen(str), &reply);
-+ return;
-+ }
-+ page = mem_map + nr;
-+ if (PageReserved(page))
-+ page = ZERO_PAGE(0);
-+
-+// kaddr = (char *)kmap_atomic(page, KM_NETDUMP);
-+
-+ for (i = 0; i < nr_chunks; i++) {
-+ unsigned int offset = i*1024;
-+ reply.code = REPLY_MEM;
-+ reply.info = offset;
-+ send_netdump_skb(dev, kaddr + offset, 1024, &reply);
-+ }
-+
-+// kunmap_atomic(kaddr, KM_NETDUMP);
-+}
-+
-+
-+/*
-+ * This function waits for the client to acknowledge the receipt
-+ * of the netdump startup reply, with the possibility of packets
-+ * getting lost. We resend the startup packet if no ACK is received,
-+ * after a 1 second delay.
-+ *
-+ * (The client can test the success of the handshake via the HELLO
-+ * command, and send ACKs until we enter netdump mode.)
-+ */
-+static void netdump_startup_handshake(struct net_device *dev)
-+{
-+ char tmp[200];
-+ reply_t reply;
-+ req_t *req = NULL;
-+ int i;
-+
-+ netdump_mode = 1;
-+
-+repeat:
-+ sprintf(tmp, "NETDUMP start, waiting for start-ACK.\n");
-+ reply.code = REPLY_START_NETDUMP;
-+ reply.nr = 0;
-+ reply.info = 0;
-+ send_netdump_skb(dev, tmp, strlen(tmp), &reply);
-+
-+ for (i = 0; i < 10000; i++) {
-+ // wait 1 sec.
-+ udelay(100);
-+ Dprintk("handshake: polling controller ...\n");
-+ netdump_poll(dev);
-+ zap_completion_queue();
-+ req = get_new_req();
-+ if (req)
-+ break;
-+ }
-+ if (!req)
-+ goto repeat;
-+ if (req->command != COMM_START_NETDUMP_ACK) {
-+ kfree(req);
-+ goto repeat;
-+ }
-+ kfree(req);
-+
-+ printk("NETDUMP START!\n");
-+}
-+
-+#if 0
-+
-+static inline void print_status (req_t *req)
-+{
-+ static int count = 0;
-+
-+ switch (++count & 3) {
-+ case 0: printk("/\r"); break;
-+ case 1: printk("|\r"); break;
-+ case 2: printk("\\\r"); break;
-+ case 3: printk("-\r"); break;
-+ }
-+}
-+
-+#else
-+
-+static inline void print_status (req_t *req)
-+{
-+ static int count = 0;
-+ static int prev_jiffies = 0;
-+
-+ if (jiffies/HZ != prev_jiffies/HZ) {
-+ prev_jiffies = jiffies;
-+ count++;
-+ switch (count & 3) {
-+ case 0: printk("%d(%ld)/\r", nr_req, jiffies); break;
-+ case 1: printk("%d(%ld)|\r", nr_req, jiffies); break;
-+ case 2: printk("%d(%ld)\\\r", nr_req, jiffies); break;
-+ case 3: printk("%d(%ld)-\r", nr_req, jiffies); break;
-+ }
-+ }
-+}
-+
-+#endif
-+
-+#define CLI 1
-+
-+#if CONFIG_SMP
-+static void freeze_cpu (void * dummy)
-+{
-+ printk("CPU#%d is frozen.\n", smp_processor_id());
-+#if CLI
-+ for (;;) __cli();
-+#else
-+ for (;;) __sti();
-+#endif
-+}
-+#endif
-+
-+static void netconsole_netdump (struct pt_regs *regs)
-+{
-+ reply_t reply;
-+ char tmp[200];
-+ unsigned long flags;
-+ struct net_device *dev = netconsole_dev;
-+ unsigned long esp;
-+ unsigned short ss;
-+ struct pt_regs myregs;
-+ req_t *req;
-+
-+ __save_flags(flags);
-+ __cli();
-+#if CONFIG_X86_LOCAL_APIC
-+ //nmi_watchdog = 0;
-+#endif
-+#if CONFIG_SMP
-+ smp_call_function(freeze_cpu, NULL, 1, 0);
-+#endif
-+ mdelay(1000);
-+ /*
-+ * Just in case we are crashing within the networking code
-+ * ... attempt to fix up.
-+ */
-+ spin_lock_init(&dev->xmit_lock);
-+
-+ esp = (unsigned long) ((char *)regs + sizeof (struct pt_regs));
-+ ss = __KERNEL_DS;
-+ if (regs->xcs & 3) {
-+ esp = regs->esp;
-+ ss = regs->xss & 0xffff;
-+ }
-+ myregs = *regs;
-+ myregs.esp = esp;
-+ myregs.xss = (myregs.xss & 0xffff0000) | ss;
-+
-+ rdtscll(t0);
-+
-+ printk("< netdump activated - performing handshake with the client. >\n");
-+ netdump_startup_handshake(dev);
-+
-+ printk("< handshake completed - listening for dump requests. >\n");
-+
-+ while (netdump_mode) {
-+ __cli();
-+ Dprintk("main netdump loop: polling controller ...\n");
-+ netdump_poll(dev);
-+ zap_completion_queue();
-+#if !CLI
-+ __sti();
-+#endif
-+ req = get_new_req();
-+ if (!req)
-+ continue;
-+ Dprintk("got new req, command %d.\n", req->command);
-+ print_status(req);
-+ switch (req->command) {
-+ case COMM_NONE:
-+ Dprintk("got NO command.\n");
-+ break;
-+
-+ case COMM_SEND_MEM:
-+ Dprintk("got MEM command.\n");
-+ // send ->from ->to.
-+ send_netdump_mem(dev, req);
-+ break;
-+
-+ case COMM_EXIT:
-+ Dprintk("got EXIT command.\n");
-+ netdump_mode = 0;
-+ break;
-+
-+ case COMM_REBOOT:
-+ Dprintk("got REBOOT command.\n");
-+ printk("netdump: rebooting in 3 seconds.\n");
-+ mdelay(3000);
-+ machine_restart(NULL);
-+ break;
-+
-+ case COMM_HELLO:
-+ sprintf(tmp, "Hello, this is netdump version 0.%02d\n", NETCONSOLE_VERSION);
-+ reply.code = REPLY_HELLO;
-+ reply.nr = req->nr;
-+ reply.info = NETCONSOLE_VERSION;
-+ send_netdump_skb(dev, tmp, strlen(tmp), &reply);
-+ break;
-+
-+ case COMM_GET_PAGE_SIZE:
-+ sprintf(tmp, "PAGE_SIZE: %ld\n", PAGE_SIZE);
-+ reply.code = REPLY_PAGE_SIZE;
-+ reply.nr = req->nr;
-+ reply.info = PAGE_SIZE;
-+ send_netdump_skb(dev, tmp, strlen(tmp), &reply);
-+ break;
-+
-+ case COMM_GET_REGS:
-+ {
-+ char *tmp2 = tmp;
-+ elf_gregset_t elf_regs;
-+
-+ reply.code = REPLY_REGS;
-+ reply.nr = req->nr;
-+ reply.info = max_mapnr;
-+ tmp2 = tmp + sprintf(tmp, "Sending register info.\n");
-+ ELF_CORE_COPY_REGS(elf_regs, regs);
-+ memcpy(tmp2, &elf_regs, sizeof(elf_regs));
-+ send_netdump_skb(dev, tmp, strlen(tmp) + sizeof(elf_regs), &reply);
-+ break;
-+ }
-+
-+ case COMM_GET_NR_PAGES:
-+ reply.code = REPLY_NR_PAGES;
-+ reply.nr = req->nr;
-+ reply.info = max_mapnr;
-+ sprintf(tmp, "Number of pages: %ld\n", max_mapnr);
-+ send_netdump_skb(dev, tmp, strlen(tmp), &reply);
-+ break;
-+
-+ case COMM_SHOW_STATE:
-+ netdump_mode = 0;
-+ //if (regs)
-+ //show_regs(regs);
-+ //show_state();
-+ //show_mem();
-+ netdump_mode = 1;
-+ reply.code = REPLY_SHOW_STATE;
-+ reply.nr = req->nr;
-+ reply.info = 0;
-+ send_netdump_skb(dev, tmp, strlen(tmp), &reply);
-+ break;
-+
-+ default:
-+ reply.code = REPLY_ERROR;
-+ reply.nr = req->nr;
-+ reply.info = req->command;
-+ Dprintk("got UNKNOWN command!\n");
-+ sprintf(tmp, "Got unknown command code %d!\n", req->command);
-+ send_netdump_skb(dev, tmp, strlen(tmp), &reply);
-+ break;
-+ }
-+ kfree(req);
-+ req = NULL;
-+ }
-+ sprintf(tmp, "NETDUMP end.\n");
-+ reply.code = REPLY_END_NETDUMP;
-+ reply.nr = 0;
-+ reply.info = 0;
-+ send_netdump_skb(dev, tmp, strlen(tmp), &reply);
-+ printk("NETDUMP END!\n");
-+ __restore_flags(flags);
-+}
-+static int netconsole_sysrq_schedule(void *arg)
-+{
-+ struct task_struct *tsk = current;
-+
-+ sprintf(tsk->comm, "sysrq_schedule");
-+ sigfillset(&tsk->blocked);
-+
-+ /* main loop */
-+ thread_stopped = 0;
-+ for (;;) {
-+ wait_event_interruptible(sysrq_thread_queue,
-+ !list_empty(&request_list) || stop_sysrq_thread);
-+ while (!list_empty(&request_list)) {
-+ req_t *req = get_new_req();
-+ Dprintk("get new req %d from req_list\n", (int)req->command);
-+ if (req->command == COMM_SYSRQ)
-+ netconsole_do_sysrq(req);
-+ }
-+ if (stop_sysrq_thread)
-+ break;
-+ wake_up(&sysrq_thread_waiter_queue);
-+ }
-+ thread_stopped = 1;
-+ wake_up(&sysrq_thread_waiter_queue);
-+ return 0;
-+}
-+
-+
-+static char *dev;
-+static int netdump_target_eth_byte0 = 255;
-+static int netdump_target_eth_byte1 = 255;
-+static int netdump_target_eth_byte2 = 255;
-+static int netdump_target_eth_byte3 = 255;
-+static int netdump_target_eth_byte4 = 255;
-+static int netdump_target_eth_byte5 = 255;
-+
-+static int netlog_target_eth_byte0 = 255;
-+static int netlog_target_eth_byte1 = 255;
-+static int netlog_target_eth_byte2 = 255;
-+static int netlog_target_eth_byte3 = 255;
-+static int netlog_target_eth_byte4 = 255;
-+static int netlog_target_eth_byte5 = 255;
-+
-+static int syslog_target_eth_byte0 = 255;
-+static int syslog_target_eth_byte1 = 255;
-+static int syslog_target_eth_byte2 = 255;
-+static int syslog_target_eth_byte3 = 255;
-+static int syslog_target_eth_byte4 = 255;
-+static int syslog_target_eth_byte5 = 255;
-+
-+MODULE_PARM(netdump_target_ip, "i");
-+MODULE_PARM_DESC(netdump_target_ip,
-+ "remote netdump IP address as a native (not network) endian integer");
-+MODULE_PARM(netlog_target_ip, "i");
-+MODULE_PARM_DESC(netlog_target_ip,
-+ "remote netlog IP address as a native (not network) endian integer");
-+MODULE_PARM(syslog_target_ip, "i");
-+MODULE_PARM_DESC(syslog_target_ip,
-+ "remote syslog IP address as a native (not network) endian integer");
-+
-+MODULE_PARM(source_port, "h");
-+MODULE_PARM_DESC(source_port,
-+ "local port from which to send netdump packets");
-+
-+MODULE_PARM(netdump_target_port, "h");
-+MODULE_PARM_DESC(netdump_target_port,
-+ "remote port to which to send netdump packets");
-+MODULE_PARM(netlog_target_port, "h");
-+MODULE_PARM_DESC(netlog_target_port,
-+ "remote port to which to send netlog packets");
-+MODULE_PARM(syslog_target_port, "h");
-+MODULE_PARM_DESC(syslog_target_port,
-+ "remote port to which to send syslog packets");
-+
-+#define ETH_BYTE(name,nr) \
-+ MODULE_PARM(name##_target_eth_byte##nr, "i"); \
-+ MODULE_PARM_DESC(name##_target_eth_byte##nr, \
-+ "byte "#nr" of the netdump server MAC address")
-+
-+#define ETH_BYTES(name) \
-+ ETH_BYTE(name, 0); ETH_BYTE(name, 1); ETH_BYTE(name, 2); \
-+ ETH_BYTE(name, 3); ETH_BYTE(name, 4); ETH_BYTE(name, 5);
-+
-+ETH_BYTES(netdump);
-+ETH_BYTES(netlog);
-+ETH_BYTES(syslog);
-+
-+MODULE_PARM(magic1, "i");
-+MODULE_PARM_DESC(magic1,
-+ "lower 32 bits of magic cookie shared between client and server");
-+MODULE_PARM(magic2, "i");
-+MODULE_PARM_DESC(magic2,
-+ "upper 32 bits of magic cookie shared between client and server");
-+MODULE_PARM(dev, "s");
-+MODULE_PARM_DESC(dev,
-+ "name of the device from which to send netdump and syslog packets");
-+MODULE_PARM(mhz, "i");
-+MODULE_PARM_DESC(mhz,
-+ "one second wall clock time takes this many million CPU cycles");
-+MODULE_PARM(idle_timeout, "i");
-+MODULE_PARM_DESC(idle_timeout,
-+ "reboot system after this many idle seconds");
-+
-+static struct console netconsole =
-+ { flags: CON_ENABLED, write: write_netconsole_msg };
-+static int init_netconsole(void)
-+{
-+ struct net_device *ndev = NULL;
-+ struct in_device *in_dev;
-+ struct irqaction *action;
-+ int rc = 0;
-+
-+ printk(KERN_INFO "netlog: using network device <%s>\n", dev);
-+ // this will be valid once the device goes up.
-+ if (dev)
-+ ndev = dev_get_by_name(dev);
-+ if (!ndev) {
-+ printk(KERN_ERR "netlog: network device %s does not exist, aborting.\n", dev);
-+ return -1;
-+ }
-+ in_dev = in_dev_get(ndev);
-+ if (!in_dev) {
-+ printk(KERN_ERR "netlog: network device %s is not an IP protocol device, aborting.\n", dev);
-+ return -1;
-+ }
-+
-+ if (!magic1 || !magic2) {
-+ printk(KERN_ERR "netlog: magic cookie (magic1,magic2) not specified.\n");
-+ return -1;
-+ }
-+ netconsole_magic = magic1 + (((u64)magic2)<<32);
-+
-+ source_ip = ntohl(in_dev->ifa_list->ifa_local);
-+ if (!source_ip) {
-+ printk(KERN_ERR "netlog: network device %s has no local address, aborting.\n", dev);
-+ return -1;
-+ }
-+#define IP(x) ((unsigned char *)&source_ip)[x]
-+ printk(KERN_INFO "netlog: using source IP %u.%u.%u.%u\n",
-+ IP(3), IP(2), IP(1), IP(0));
-+#undef IP
-+ source_ip = htonl(source_ip);
-+ if (!source_port) {
-+ printk(KERN_ERR "netlog: source_port parameter not specified, aborting.\n");
-+ return -1;
-+ }
-+ printk(KERN_INFO "netlog: using source UDP port: %u\n", source_port);
-+ source_port = htons(source_port);
-+
-+ if (!netdump_target_ip && !netlog_target_ip && !syslog_target_ip) {
-+ printk(KERN_ERR "netlog: target_ip parameter not specified, aborting.\n");
-+ return -1;
-+#define IP(x) ((unsigned char *)&netdump_target_ip)[x]
-+ printk(KERN_INFO "netlog: using netdump target IP %u.%u.%u.%u\n",
-+ IP(3), IP(2), IP(1), IP(0));
-+#undef IP
-+ netdump_target_ip = htonl(netdump_target_ip);
-+ }
-+ if (netlog_target_ip) {
-+#define IP(x) ((unsigned char *)&netlog_target_ip)[x]
-+ printk(KERN_INFO "netlog: using netlog target IP %u.%u.%u.%u\n",
-+ IP(3), IP(2), IP(1), IP(0));
-+#undef IP
-+ netlog_target_ip = htonl(netlog_target_ip);
-+ }
-+ if (syslog_target_ip) {
-+ if (!syslog_target_port)
-+ syslog_target_port = 514;
-+#define IP(x) ((unsigned char *)&syslog_target_ip)[x]
-+ printk("netlog: using syslog target IP %u.%u.%u.%u, port: %d\n", IP(3), IP(2), IP(1), IP(0), syslog_target_port);
-+#undef IP
-+ syslog_target_ip = htonl(syslog_target_ip);
-+ syslog_target_port = htons(syslog_target_port);
-+ }
-+ if (!netdump_target_port && !netlog_target_port && !syslog_target_port) {
-+ printk(KERN_ERR "netlog: target_port parameter not specified, aborting.\n");
-+ return -1;
-+ }
-+ if (netdump_target_port) {
-+ printk(KERN_INFO "netlog: using target UDP port: %u\n", netdump_target_port);
-+ netdump_target_port = htons(netdump_target_port);
-+ }
-+ if (netlog_target_port) {
-+ printk(KERN_INFO "netlog: using target UDP port: %u\n", netlog_target_port);
-+ netlog_target_port = htons(netlog_target_port);
-+ }
-+
-+ netdump_daddr[0] = netdump_target_eth_byte0;
-+ netdump_daddr[1] = netdump_target_eth_byte1;
-+ netdump_daddr[2] = netdump_target_eth_byte2;
-+ netdump_daddr[3] = netdump_target_eth_byte3;
-+ netdump_daddr[4] = netdump_target_eth_byte4;
-+ netdump_daddr[5] = netdump_target_eth_byte5;
-+
-+ if ((netdump_daddr[0] & netdump_daddr[1] & netdump_daddr[2] & netdump_daddr[3] & netdump_daddr[4] & netdump_daddr[5]) == 255)
-+ printk(KERN_INFO "netlog: using broadcast ethernet frames to send netdump packets.\n");
-+ else
-+ printk(KERN_INFO "netlog: using netdump target ethernet address %02x:%02x:%02x:%02x:%02x:%02x.\n",
-+ netdump_daddr[0], netdump_daddr[1], netdump_daddr[2], netdump_daddr[3], netdump_daddr[4], netdump_daddr[5]);
-+
-+ netlog_daddr[0] = netlog_target_eth_byte0;
-+ netlog_daddr[1] = netlog_target_eth_byte1;
-+ netlog_daddr[2] = netlog_target_eth_byte2;
-+ netlog_daddr[3] = netlog_target_eth_byte3;
-+ netlog_daddr[4] = netlog_target_eth_byte4;
-+ netlog_daddr[5] = netlog_target_eth_byte5;
-+
-+ if ((netlog_daddr[0] & netlog_daddr[1] & netlog_daddr[2] & netlog_daddr[3] & netlog_daddr[4] & netlog_daddr[5]) == 255)
-+ printk(KERN_INFO "netlog: using broadcast ethernet frames to send netdump packets.\n");
-+ else
-+ printk(KERN_INFO "netlog: using netdump target ethernet address %02x:%02x:%02x:%02x:%02x:%02x.\n",
-+ netlog_daddr[0], netlog_daddr[1], netlog_daddr[2], netlog_daddr[3], netlog_daddr[4], netlog_daddr[5]);
-+ syslog_daddr[0] = syslog_target_eth_byte0;
-+ syslog_daddr[1] = syslog_target_eth_byte1;
-+ syslog_daddr[2] = syslog_target_eth_byte2;
-+ syslog_daddr[3] = syslog_target_eth_byte3;
-+ syslog_daddr[4] = syslog_target_eth_byte4;
-+ syslog_daddr[5] = syslog_target_eth_byte5;
-+
-+ if ((syslog_daddr[0] & syslog_daddr[1] & syslog_daddr[2] & syslog_daddr[3] & syslog_daddr[4] & syslog_daddr[5]) == 255)
-+ printk(KERN_INFO "netlog: using broadcast ethernet frames to send syslog packets.\n");
-+ else
-+ printk(KERN_INFO "netlog: using syslog target ethernet address %02x:%02x:%02x:%02x:%02x:%02x.\n",
-+ syslog_daddr[0], syslog_daddr[1], syslog_daddr[2], syslog_daddr[3], syslog_daddr[4], syslog_daddr[5]);
-+
-+ mhz_cycles = (unsigned long long)mhz * 1000000ULL;
-+ jiffy_cycles = (unsigned long long)mhz * (1000000/HZ);
-+
-+ ndev->rx_hook = netconsole_rx_hook;
-+ netdump_func = netconsole_netdump;
-+ netconsole_dev = ndev;
-+ /* find irq function of the ndev*/
-+ action=find_irq_action(ndev->irq, ndev);
-+ if (!action) {
-+ printk(KERN_ERR "couldn't find irq handler for <%s>", dev);
-+ return -1;
-+ }
-+ irqfunc = action->handler;
-+
-+ stop_sysrq_thread = 0;
-+ INIT_LIST_HEAD(&request_list);
-+ init_waitqueue_head(&sysrq_thread_queue);
-+ init_waitqueue_head(&sysrq_thread_waiter_queue);
-+ if ((rc = kernel_thread(netconsole_sysrq_schedule, NULL, 0)) < 0 ){
-+ printk(KERN_ERR "Can not start netconsole sysrq thread: rc %d\n", rc);
-+ return -1;
-+ }
-+
-+#define STARTUP_MSG "[...network console startup...]\n"
-+ write_netconsole_msg(NULL, STARTUP_MSG, strlen(STARTUP_MSG));
-+
-+ register_console(&netconsole);
-+ printk(KERN_INFO "netlog: network logging started up successfully!\n");
-+ return 0;
-+}
-+
-+static void cleanup_netconsole(void)
-+{
-+ stop_sysrq_thread = 1;
-+
-+ wake_up(&sysrq_thread_queue);
-+ wait_event(sysrq_thread_waiter_queue, thread_stopped);
-+ printk(KERN_INFO"netlog: network logging shut down.\n");
-+ unregister_console(&netconsole);
-+
-+#define SHUTDOWN_MSG "[...network console shutdown...]\n"
-+ write_netconsole_msg(NULL, SHUTDOWN_MSG, strlen(SHUTDOWN_MSG));
-+ netconsole_dev->rx_hook = NULL;
-+ netconsole_dev = NULL;
-+}
-+
-+module_init(init_netconsole);
-+module_exit(cleanup_netconsole);
-+
-+MODULE_LICENSE("GPL");
-+
-Index: linux-2.4.24/drivers/net/netconsole.h
-===================================================================
---- linux-2.4.24.orig/drivers/net/netconsole.h 2003-01-30 18:24:37.000000000 +0800
-+++ linux-2.4.24/drivers/net/netconsole.h 2004-06-09 14:14:54.000000000 +0800
-@@ -0,0 +1,102 @@
-+/*
-+ * linux/drivers/net/netconsole.h
-+ *
-+ * Copyright (C) 2001 Ingo Molnar <mingo@redhat.com>
-+ *
-+ * This file contains the implementation of an IRQ-safe, crash-safe
-+ * kernel console implementation that outputs kernel messages to the
-+ * network.
-+ *
-+ * Modification history:
-+ *
-+ * 2001-09-17 started by Ingo Molnar.
-+ */
-+
-+/****************************************************************
-+ * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ ****************************************************************/
-+
-+#define NETCONSOLE_VERSION 0x03
-+
-+enum netdump_commands {
-+ COMM_NONE = 0,
-+ COMM_SEND_MEM = 1,
-+ COMM_EXIT = 2,
-+ COMM_REBOOT = 3,
-+ COMM_HELLO = 4,
-+ COMM_GET_NR_PAGES = 5,
-+ COMM_GET_PAGE_SIZE = 6,
-+ COMM_START_NETDUMP_ACK = 7,
-+ COMM_GET_REGS = 8,
-+ COMM_SHOW_STATE = 9,
-+ COMM_START_WRITE_NETDUMP_ACK = 10,
-+ COMM_SYSRQ = 11,
-+};
-+
-+#define NETDUMP_REQ_SIZE (8+4*4)
-+
-+typedef struct netdump_req_s {
-+ u64 magic;
-+ u32 nr;
-+ u32 command;
-+ u32 from;
-+ u32 to;
-+ struct list_head list;
-+} req_t;
-+
-+enum netdump_replies {
-+ REPLY_NONE = 0,
-+ REPLY_ERROR = 1,
-+ REPLY_LOG = 2,
-+ REPLY_MEM = 3,
-+ REPLY_RESERVED = 4,
-+ REPLY_HELLO = 5,
-+ REPLY_NR_PAGES = 6,
-+ REPLY_PAGE_SIZE = 7,
-+ REPLY_START_NETDUMP = 8,
-+ REPLY_END_NETDUMP = 9,
-+ REPLY_REGS = 10,
-+ REPLY_MAGIC = 11,
-+ REPLY_SHOW_STATE = 12,
-+ REPLY_SYSRQ = 13,
-+};
-+
-+typedef struct netdump_reply_s {
-+ u32 nr;
-+ u32 code;
-+ u32 info;
-+} reply_t;
-+
-+#define HEADER_LEN (1 + sizeof(reply_t))
-+/* for netconsole */
-+static inline void get_current_regs(struct pt_regs *regs)
-+{
-+ __asm__ __volatile__("movl %%ebx,%0" : "=m"(regs->ebx));
-+ __asm__ __volatile__("movl %%ecx,%0" : "=m"(regs->ecx));
-+ __asm__ __volatile__("movl %%edx,%0" : "=m"(regs->edx));
-+ __asm__ __volatile__("movl %%esi,%0" : "=m"(regs->esi));
-+ __asm__ __volatile__("movl %%edi,%0" : "=m"(regs->edi));
-+ __asm__ __volatile__("movl %%ebp,%0" : "=m"(regs->ebp));
-+ __asm__ __volatile__("movl %%eax,%0" : "=m"(regs->eax));
-+ __asm__ __volatile__("movl %%esp,%0" : "=m"(regs->esp));
-+ __asm__ __volatile__("movw %%ss, %%ax;" :"=a"(regs->xss));
-+ __asm__ __volatile__("movw %%cs, %%ax;" :"=a"(regs->xcs));
-+ __asm__ __volatile__("movw %%ds, %%ax;" :"=a"(regs->xds));
-+ __asm__ __volatile__("movw %%es, %%ax;" :"=a"(regs->xes));
-+ __asm__ __volatile__("pushfl; popl %0" :"=m"(regs->eflags));
-+ regs->eip = (unsigned long)current_text_addr();
-+}
-+
-Index: linux-2.4.24/drivers/net/Makefile
-===================================================================
---- linux-2.4.24.orig/drivers/net/Makefile 2003-11-29 02:26:20.000000000 +0800
-+++ linux-2.4.24/drivers/net/Makefile 2004-06-09 14:16:14.000000000 +0800
-@@ -250,6 +250,8 @@
- obj-y += ../acorn/net/acorn-net.o
- endif
-
-+obj-$(CONFIG_NETCONSOLE) += netconsole.o
-+
- #
- # HIPPI adapters
- #
-Index: linux-2.4.24/drivers/net/Config.in
-===================================================================
---- linux-2.4.24.orig/drivers/net/Config.in 2003-11-29 02:26:20.000000000 +0800
-+++ linux-2.4.24/drivers/net/Config.in 2004-06-09 14:17:33.000000000 +0800
-@@ -294,7 +294,7 @@
- fi
- dep_tristate ' SysKonnect FDDI PCI support' CONFIG_SKFP $CONFIG_PCI
- fi
--
-+tristate 'Network logging support' CONFIG_NETCONSOLE
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- if [ "$CONFIG_INET" = "y" ]; then
- bool 'HIPPI driver support (EXPERIMENTAL)' CONFIG_HIPPI
-Index: linux-2.4.24/arch/i386/kernel/traps.c
-===================================================================
---- linux-2.4.24.orig/arch/i386/kernel/traps.c 2004-06-09 14:10:04.000000000 +0800
-+++ linux-2.4.24/arch/i386/kernel/traps.c 2004-06-09 14:29:00.000000000 +0800
-@@ -279,6 +279,8 @@
- bug:
- printk("Kernel BUG\n");
- }
-+void (*netdump_func) (struct pt_regs *regs) = NULL;
-+int netdump_mode = 0;
-
- spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
-
-@@ -290,6 +292,8 @@
- handle_BUG(regs);
- printk("%s: %04lx\n", str, err & 0xffff);
- show_registers(regs);
-+ if (netdump_func)
-+ netdump_func(regs);
- bust_spinlocks(0);
- spin_unlock_irq(&die_lock);
- do_exit(SIGSEGV);
-@@ -1039,5 +1043,7 @@
- return -ENOSYS;
- }
-
-+EXPORT_SYMBOL_GPL(netdump_func);
-+EXPORT_SYMBOL_GPL(netdump_mode);
- EXPORT_SYMBOL_GPL(is_kernel_text_address);
- EXPORT_SYMBOL_GPL(lookup_symbol);
-Index: linux-2.4.24/arch/i386/kernel/irq.c
-===================================================================
---- linux-2.4.24.orig/arch/i386/kernel/irq.c 2004-06-09 14:09:59.000000000 +0800
-+++ linux-2.4.24/arch/i386/kernel/irq.c 2004-06-09 14:53:34.000000000 +0800
-@@ -1048,6 +1048,21 @@
- return 0;
- }
-
-+struct irqaction *find_irq_action(unsigned int irq, void *dev_id)
-+{
-+ struct irqaction *a, *r=0;
-+
-+ spin_lock_irq(&irq_desc[irq].lock);
-+ for(a=irq_desc[irq].action; a; a=a->next) {
-+ if(a->dev_id == dev_id) {
-+ r=a;
-+ break;
-+ }
-+ }
-+ spin_unlock_irq(&irq_desc[irq].lock);
-+ return r;
-+}
-+
- static struct proc_dir_entry * root_irq_dir;
- static struct proc_dir_entry * irq_dir [NR_IRQS];
-
-Index: linux-2.4.24/arch/i386/kernel/i386_ksyms.c
-===================================================================
---- linux-2.4.24.orig/arch/i386/kernel/i386_ksyms.c 2003-11-29 02:26:19.000000000 +0800
-+++ linux-2.4.24/arch/i386/kernel/i386_ksyms.c 2004-06-09 14:55:11.000000000 +0800
-@@ -66,6 +66,7 @@
- EXPORT_SYMBOL(iounmap);
- EXPORT_SYMBOL(enable_irq);
- EXPORT_SYMBOL(disable_irq);
-+EXPORT_SYMBOL(find_irq_action);
- EXPORT_SYMBOL(disable_irq_nosync);
- EXPORT_SYMBOL(probe_irq_mask);
- EXPORT_SYMBOL(kernel_thread);
-Index: linux-2.4.24/arch/x86_64/kernel/traps.c
-===================================================================
---- linux-2.4.24.orig/arch/x86_64/kernel/traps.c 2003-11-29 02:26:19.000000000 +0800
-+++ linux-2.4.24/arch/x86_64/kernel/traps.c 2004-06-09 14:30:02.000000000 +0800
-@@ -80,7 +80,7 @@
- extern char iret_address[];
-
- struct notifier_block *die_chain;
--
-+void (*netdump_func) (struct pt_regs *regs) = NULL;
- int kstack_depth_to_print = 12;
-
- #ifdef CONFIG_KALLSYMS
-Index: linux-2.4.24/arch/x86_64/kernel/x8664_ksyms.c
-===================================================================
---- linux-2.4.24.orig/arch/x86_64/kernel/x8664_ksyms.c 2003-11-29 02:26:19.000000000 +0800
-+++ linux-2.4.24/arch/x86_64/kernel/x8664_ksyms.c 2004-06-09 14:32:14.000000000 +0800
-@@ -40,7 +40,7 @@
- extern struct drive_info_struct drive_info;
- EXPORT_SYMBOL(drive_info);
- #endif
--
-+int netdump_mode = 0;
- /* platform dependent support */
- EXPORT_SYMBOL(boot_cpu_data);
- EXPORT_SYMBOL(dump_fpu);
-@@ -226,6 +226,9 @@
- extern void int_ret_from_sys_call(void);
- EXPORT_SYMBOL_NOVERS(int_ret_from_sys_call);
-
-+EXPORT_SYMBOL_GPL(netdump_func);
-+EXPORT_SYMBOL_GPL(netdump_mode);
-+
- EXPORT_SYMBOL(touch_nmi_watchdog);
-
- EXPORT_SYMBOL(do_fork);
-Index: linux-2.4.24/include/linux/netdevice.h
-===================================================================
---- linux-2.4.24.orig/include/linux/netdevice.h 2004-06-09 14:20:33.000000000 +0800
-+++ linux-2.4.24/include/linux/netdevice.h 2004-06-09 18:40:24.000000000 +0800
-@@ -435,6 +435,7 @@
- unsigned char *haddr);
- int (*neigh_setup)(struct net_device *dev, struct neigh_parms *);
- int (*accept_fastpath)(struct net_device *, struct dst_entry*);
-+ int (*rx_hook)(struct sk_buff *skb);
-
- /* open/release and usage marking */
- struct module *owner;
-Index: linux-2.4.24/include/linux/kernel.h
-===================================================================
---- linux-2.4.24.orig/include/linux/kernel.h 2004-06-09 14:20:33.000000000 +0800
-+++ linux-2.4.24/include/linux/kernel.h 2004-06-09 18:39:18.000000000 +0800
-@@ -105,6 +105,9 @@
- extern void bust_spinlocks(int yes);
- extern int oops_in_progress; /* If set, an oops, panic(), BUG() or die() is in progress */
-
-+extern void (*netdump_func) (struct pt_regs *regs);
-+extern int netdump_mode;
-+
- extern int tainted;
- extern const char *print_tainted(void);
-
-Index: linux-2.4.24/include/asm-i386/irq.h
-===================================================================
---- linux-2.4.24.orig/include/asm-i386/irq.h 2004-06-09 14:20:33.000000000 +0800
-+++ linux-2.4.24/include/asm-i386/irq.h 2004-06-09 14:54:04.000000000 +0800
-@@ -38,7 +38,7 @@
- extern void disable_irq_nosync(unsigned int);
- extern void enable_irq(unsigned int);
- extern void release_x86_irqs(struct task_struct *);
--
-+extern struct irqaction *find_irq_action(unsigned int irq, void *dev_id);
- #ifdef CONFIG_X86_LOCAL_APIC
- #define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */
- #endif
-Index: linux-2.4.24/net/core/dev.c
-===================================================================
---- linux-2.4.24.orig/net/core/dev.c 2003-11-29 02:26:21.000000000 +0800
-+++ linux-2.4.24/net/core/dev.c 2004-06-09 14:50:03.000000000 +0800
-@@ -1287,7 +1287,13 @@
- queue = &softnet_data[this_cpu];
-
- local_irq_save(flags);
--
-+ if (unlikely(skb->dev->rx_hook != NULL)) {
-+ int ret;
-+
-+ ret = skb->dev->rx_hook(skb);
-+ if (ret == NET_RX_DROP)
-+ goto drop;
-+ }
- netdev_rx_stat[this_cpu].total++;
- if (queue->input_pkt_queue.qlen <= netdev_max_backlog) {
- if (queue->input_pkt_queue.qlen) {
+++ /dev/null
-Index: lum/fs/Makefile
-===================================================================
---- lum.orig/fs/Makefile 2004-06-07 17:25:22.000000000 -0400
-+++ lum/fs/Makefile 2004-06-07 17:25:22.000000000 -0400
-@@ -7,7 +7,8 @@
-
- O_TARGET := fs.o
-
--export-objs := filesystems.o open.o dcache.o buffer.o dquot.o inode.o
-+export-objs := filesystems.o open.o dcache.o buffer.o dquot.o inode.o \
-+ namei.o file_table.o
- mod-subdirs := nls
-
- obj-y := open.o read_write.o devices.o file_table.o buffer.o \
-Index: lum/fs/file_table.c
-===================================================================
---- lum.orig/fs/file_table.c 2002-11-28 18:53:15.000000000 -0500
-+++ lum/fs/file_table.c 2004-06-07 17:25:22.000000000 -0400
-@@ -82,7 +82,8 @@
- * and call the open function (if any). The caller must verify that
- * inode->i_fop is not NULL.
- */
--int init_private_file(struct file *filp, struct dentry *dentry, int mode)
-+int init_private_file_it(struct file *filp, struct dentry *dentry, int mode,
-+ struct lookup_intent *it)
- {
- memset(filp, 0, sizeof(*filp));
- filp->f_mode = mode;
-@@ -90,12 +91,20 @@
- filp->f_dentry = dentry;
- filp->f_uid = current->fsuid;
- filp->f_gid = current->fsgid;
-+ if (it)
-+ filp->f_it = it;
- filp->f_op = dentry->d_inode->i_fop;
- if (filp->f_op->open)
- return filp->f_op->open(dentry->d_inode, filp);
- else
- return 0;
- }
-+EXPORT_SYMBOL(init_private_file_it);
-+
-+int init_private_file(struct file *filp, struct dentry *dentry, int mode)
-+{
-+ return init_private_file_it(filp, dentry, mode, NULL);
-+}
-
- void fput(struct file * file)
- {
-Index: lum/fs/inode.c
-===================================================================
---- lum.orig/fs/inode.c 2004-06-07 17:25:22.000000000 -0400
-+++ lum/fs/inode.c 2004-06-07 17:25:22.000000000 -0400
-@@ -1045,9 +1045,10 @@
- }
-
-
--struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque)
-+static inline struct inode *ifind(struct super_block *sb, unsigned long ino,
-+ struct list_head *head,
-+ find_inode_t find_actor, void *opaque)
- {
-- struct list_head * head = inode_hashtable + hash(sb,ino);
- struct inode * inode;
-
- spin_lock(&inode_lock);
-@@ -1060,6 +1061,24 @@
- }
- spin_unlock(&inode_lock);
-
-+ return NULL;
-+}
-+
-+struct inode *ilookup4(struct super_block *sb, unsigned long ino,
-+ find_inode_t find_actor, void *opaque)
-+{
-+ struct list_head * head = inode_hashtable + hash(sb,ino);
-+ return ifind(sb, ino, head, find_actor, opaque);
-+}
-+
-+struct inode *iget4(struct super_block *sb, unsigned long ino,
-+ find_inode_t find_actor, void *opaque)
-+{
-+ struct list_head * head = inode_hashtable + hash(sb,ino);
-+ struct inode *inode = ifind(sb, ino, head, find_actor, opaque);
-+ if (inode)
-+ return inode;
-+
- /*
- * get_new_inode() will do the right thing, re-trying the search
- * in case it had to block at any point.
-Index: lum/fs/namei.c
-===================================================================
---- lum.orig/fs/namei.c 2004-06-07 17:24:47.000000000 -0400
-+++ lum/fs/namei.c 2004-06-07 18:08:28.000000000 -0400
-@@ -22,6 +22,7 @@
- #include <linux/dnotify.h>
- #include <linux/smp_lock.h>
- #include <linux/personality.h>
-+#include <linux/module.h>
-
- #include <asm/namei.h>
- #include <asm/uaccess.h>
-@@ -100,6 +101,7 @@
- it->it_op_release(it);
-
- }
-+EXPORT_SYMBOL(intent_release);
-
- /* In order to reduce some races, while at the same time doing additional
- * checking and hopefully speeding things up, we copy filenames to the
-@@ -907,7 +909,8 @@
-
-
- /* SMP-safe */
--struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
-+struct dentry * lookup_one_len_it(const char * name, struct dentry * base,
-+ int len, struct lookup_intent *it)
- {
- unsigned long hash;
- struct qstr this;
-@@ -927,11 +930,16 @@
- }
- this.hash = end_name_hash(hash);
-
-- return lookup_hash_it(&this, base, NULL, NULL);
-+ return lookup_hash_it(&this, base, NULL, it);
- access:
- return ERR_PTR(-EACCES);
- }
-
-+struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
-+{
-+ return lookup_one_len_it(name, base, len, NULL);
-+}
-+
- /*
- * namei()
- *
-Index: lum/fs/nfsd/export.c
-===================================================================
---- lum.orig/fs/nfsd/export.c 2003-11-28 13:26:21.000000000 -0500
-+++ lum/fs/nfsd/export.c 2004-06-07 17:25:22.000000000 -0400
-@@ -223,6 +223,11 @@
- inode = nd.dentry->d_inode;
- dev = inode->i_dev;
- ino = inode->i_ino;
-+ if ((inode->i_sb->s_type->fs_flags & FS_NFSEXP_FSID) &&
-+ !(nxp->ex_flags & NFSEXP_FSID)) {
-+ nxp->ex_dev = inode->i_sb->s_dev;
-+ nxp->ex_flags |= NFSEXP_FSID;
-+ }
- err = -EINVAL;
-
- exp = exp_get(clp, dev, ino);
-Index: lum/fs/nfsd/nfsfh.c
-===================================================================
---- lum.orig/fs/nfsd/nfsfh.c 2003-11-28 13:26:21.000000000 -0500
-+++ lum/fs/nfsd/nfsfh.c 2004-06-07 17:51:58.000000000 -0400
-@@ -36,6 +36,15 @@
- int sequence; /* sequence counter */
- };
-
-+static struct dentry *lookup_it(struct inode *inode, struct dentry * dentry)
-+{
-+ if (inode->i_op->lookup_it)
-+ return inode->i_op->lookup_it(inode, dentry, NULL, NULL, 0);
-+ else
-+ return inode->i_op->lookup(inode, dentry);
-+
-+}
-+
- /*
- * A rather strange filldir function to capture
- * the name matching the specified inode number.
-@@ -75,6 +84,8 @@
- int error;
- struct file file;
- struct nfsd_getdents_callback buffer;
-+ struct lookup_intent it;
-+ struct file *filp = NULL;
-
- error = -ENOTDIR;
- if (!dir || !S_ISDIR(dir->i_mode))
-@@ -85,9 +96,37 @@
- /*
- * Open the directory ...
- */
-- error = init_private_file(&file, dentry, FMODE_READ);
-- if (error)
-+ if (dentry->d_op && dentry->d_op->d_revalidate_it) {
-+ if ((dentry->d_flags & DCACHE_NFSD_DISCONNECTED) &&
-+ (dentry->d_parent == dentry) ) {
-+ it.it_op_release = NULL;
-+ /*
-+ * XXX Temporary Hack: Simulating init_private_file without
-+ * f_op->open for disconnected dentry Since we don't have actual
-+ * dentry->d_name to revalidate in revalidate_it()
-+ */
-+ filp = &file;
-+ memset(filp, 0, sizeof(*filp));
-+ filp->f_mode = FMODE_READ;
-+ atomic_set(&filp->f_count, 1);
-+ filp->f_dentry = dentry;
-+ filp->f_uid = current->fsuid;
-+ filp->f_gid = current->fsgid;
-+ filp->f_op = dentry->d_inode->i_fop;
-+ error = 0;
-+ } else {
-+ intent_init(&it, IT_OPEN, 0);
-+ error = revalidate_it(dentry, &it);
-+ if (error)
-+ goto out;
-+ error = init_private_file_it(&file, dentry, FMODE_READ, &it);
-+ }
-+ } else {
-+ error = init_private_file_it(&file, dentry, FMODE_READ, NULL);
-+ }
-+ if (error)
- goto out;
-+
- error = -EINVAL;
- if (!file.f_op->readdir)
- goto out_close;
-@@ -113,9 +152,13 @@
- }
-
- out_close:
-- if (file.f_op->release)
-+ if (file.f_op->release && !filp)
- file.f_op->release(dir, &file);
- out:
-+ if (dentry->d_op &&
-+ dentry->d_op->d_revalidate_it &&
-+ it.it_op_release && !filp)
-+ intent_release(&it);
- return error;
- }
-
-@@ -274,7 +317,7 @@
- * it is well connected. But nobody returns different dentrys do they?
- */
- down(&child->d_inode->i_sem);
-- pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry);
-+ pdentry = lookup_it(child->d_inode, tdentry);
- up(&child->d_inode->i_sem);
- d_drop(tdentry); /* we never want ".." hashed */
- if (!pdentry && tdentry->d_inode == NULL) {
-@@ -307,6 +350,8 @@
- pdentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
- pdentry->d_op = child->d_op;
- }
-+ if (child->d_op && child->d_op->d_revalidate_it)
-+ pdentry->d_op = child->d_op;
- }
- if (pdentry == NULL)
- pdentry = ERR_PTR(-ENOMEM);
-@@ -464,6 +509,8 @@
- struct dentry *pdentry;
- struct inode *parent;
-
-+ if (result->d_op && result->d_op->d_revalidate_it)
-+ dentry->d_op = result->d_op;
- pdentry = nfsd_findparent(dentry);
- err = PTR_ERR(pdentry);
- if (IS_ERR(pdentry))
-@@ -670,6 +717,11 @@
-
- inode = dentry->d_inode;
-
-+ /* cache coherency for non-device filesystems */
-+ if (inode->i_op && inode->i_op->revalidate_it) {
-+ inode->i_op->revalidate_it(dentry, NULL);
-+ }
-+
- /* Type check. The correct error return for type mismatches
- * does not seem to be generally agreed upon. SunOS seems to
- * use EISDIR if file isn't S_IFREG; a comment in the NFSv3
-@@ -903,8 +955,9 @@
- dentry->d_parent->d_name.name, dentry->d_name.name);
- goto out;
- out_uptodate:
-- printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n",
-- dentry->d_parent->d_name.name, dentry->d_name.name);
-+ if(!dentry->d_parent->d_inode->i_op->mkdir_raw)
-+ printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n",
-+ dentry->d_parent->d_name.name, dentry->d_name.name);
- goto out;
- }
-
-Index: lum/fs/nfsd/vfs.c
-===================================================================
---- lum.orig/fs/nfsd/vfs.c 2003-11-28 13:26:21.000000000 -0500
-+++ lum/fs/nfsd/vfs.c 2004-06-07 17:25:22.000000000 -0400
-@@ -77,6 +77,128 @@
- static struct raparms * raparml;
- static struct raparms * raparm_cache;
-
-+static int link_raw(struct dentry *dold, struct dentry *ddir,
-+ struct dentry *dnew)
-+{
-+ int err;
-+
-+ struct nameidata old_nd = { .dentry = dold };
-+ struct nameidata nd = { .dentry = ddir, .last = dnew->d_name };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->link_raw(&old_nd, &nd);
-+ d_instantiate(dnew, dold->d_inode);
-+ if(dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it)
-+ dold->d_inode->i_op->revalidate_it(dnew, NULL);
-+
-+ return err;
-+}
-+
-+static int unlink_raw(struct dentry *dentry, char *fname, int flen,
-+ struct dentry *rdentry)
-+{
-+ int err;
-+ struct qstr last = { .name = fname, .len = flen };
-+ struct nameidata nd = { .dentry = dentry, .last = last };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->unlink_raw(&nd);
-+ if (!err)
-+ d_delete(rdentry);
-+
-+ return err;
-+}
-+
-+static int rmdir_raw(struct dentry *dentry, char *fname, int flen,
-+ struct dentry *rdentry)
-+{
-+ int err;
-+ struct qstr last = { .name = fname, .len = flen };
-+ struct nameidata nd = { .dentry = dentry, .last = last };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->rmdir_raw(&nd);
-+ if(!err) {
-+ rdentry->d_inode->i_flags |= S_DEAD;
-+ d_delete(rdentry);
-+ }
-+
-+ return err;
-+}
-+
-+static int symlink_raw(struct dentry *dentry, char *fname, int flen,
-+ char *path)
-+{
-+ int err;
-+ struct qstr last = { .name = fname, .len = flen };
-+ struct nameidata nd = { .dentry = dentry, .last = last };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->symlink_raw(&nd, path);
-+
-+ return err;
-+}
-+
-+static int mkdir_raw(struct dentry *dentry, char *fname, int flen, int mode)
-+{
-+ int err;
-+ struct qstr last = { .name = fname, .len = flen };
-+ struct nameidata nd = { .dentry = dentry, .last = last };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->mkdir_raw(&nd, mode);
-+
-+ return err;
-+}
-+
-+static int mknod_raw(struct dentry *dentry, char *fname, int flen, int mode,
-+ dev_t dev)
-+{
-+ int err;
-+ struct qstr last = { .name = fname, .len = flen };
-+ struct nameidata nd = { .dentry = dentry, .last = last };
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ err = op->mknod_raw(&nd, mode, dev);
-+
-+ return err;
-+}
-+
-+static int rename_raw(struct dentry *fdentry, struct dentry *tdentry,
-+ struct dentry *odentry, struct dentry *ndentry)
-+{
-+ int err;
-+
-+ struct nameidata old_nd = { .dentry = fdentry, .last = odentry->d_name};
-+ struct nameidata new_nd = { .dentry = tdentry, .last = ndentry->d_name};
-+ struct inode_operations *op = old_nd.dentry->d_inode->i_op;
-+ err = op->rename_raw(&old_nd, &new_nd);
-+ d_move(odentry, ndentry);
-+
-+ return err;
-+}
-+
-+static int setattr_raw(struct inode *inode, struct iattr *iap)
-+{
-+ int err;
-+
-+ iap->ia_valid |= ATTR_RAW;
-+ err = inode->i_op->setattr_raw(inode, iap);
-+
-+ return err;
-+}
-+
-+int revalidate_it(struct dentry *dentry, struct lookup_intent *it)
-+{
-+ int err = 0;
-+
-+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) {
-+ if (!dentry->d_op->d_revalidate_it(dentry, 0, NULL, it) &&
-+ !d_invalidate(dentry)) {
-+ dput(dentry);
-+ err = -EINVAL;
-+ dentry = NULL;
-+ return err;
-+ }
-+ }
-+
-+ return err;
-+}
-+
- /*
- * Look up one component of a pathname.
- * N.B. After this call _both_ fhp and resfh need an fh_put
-@@ -302,7 +424,10 @@
- }
- err = nfserr_notsync;
- if (!check_guard || guardtime == inode->i_ctime) {
-- err = notify_change(dentry, iap);
-+ if ( dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw)
-+ err = setattr_raw(dentry->d_inode, iap);
-+ else
-+ err = notify_change(dentry, iap);
- err = nfserrno(err);
- }
- if (size_change) {
-@@ -429,6 +554,7 @@
- {
- struct dentry *dentry;
- struct inode *inode;
-+ struct lookup_intent it;
- int err;
-
- /* If we get here, then the client has already done an "open", and (hopefully)
-@@ -475,6 +601,14 @@
- filp->f_mode = FMODE_READ;
- }
-
-+ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode);
-+
-+ err = revalidate_it(dentry, &it);
-+ if (err)
-+ goto out_nfserr;
-+
-+ filp->f_it = ⁢
-+
- err = 0;
- if (filp->f_op && filp->f_op->open) {
- err = filp->f_op->open(inode, filp);
-@@ -489,7 +623,11 @@
- atomic_dec(&filp->f_count);
- }
- }
-+
- out_nfserr:
-+ if (it.it_op_release)
-+ intent_release(&it);
-+
- if (err)
- err = nfserrno(err);
- out:
-@@ -820,7 +958,7 @@
- {
- struct dentry *dentry, *dchild;
- struct inode *dirp;
-- int err;
-+ int err, error = -EOPNOTSUPP;
-
- err = nfserr_perm;
- if (!flen)
-@@ -836,20 +974,44 @@
- dentry = fhp->fh_dentry;
- dirp = dentry->d_inode;
-
-+ switch (type) {
-+ case S_IFDIR:
-+ if (dirp->i_op->mkdir_raw)
-+ error = mkdir_raw(dentry, fname, flen, iap->ia_mode);
-+ break;
-+ case S_IFCHR:
-+ case S_IFBLK:
-+ case S_IFIFO:
-+ case S_IFSOCK:
-+ case S_IFREG:
-+ if (dirp->i_op->mknod_raw) {
-+ if (type == S_IFREG)
-+ rdev = 0;
-+ error = mknod_raw(dentry, fname, flen, iap->ia_mode, rdev);
-+ }
-+ break;
-+ default:
-+ printk("nfsd: bad file type %o in nfsd_create\n", type);
-+ }
-+
- err = nfserr_notdir;
-- if(!dirp->i_op || !dirp->i_op->lookup)
-+ if(!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it))
- goto out;
- /*
- * Check whether the response file handle has been verified yet.
- * If it has, the parent directory should already be locked.
- */
-- if (!resfhp->fh_dentry) {
-- /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */
-- fh_lock(fhp);
-+ if (!resfhp->fh_dentry || dirp->i_op->lookup_it) {
-+ /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create
-+ and nfsd_proc_create in case of lustre
-+ */
-+ if (!resfhp->fh_dentry)
-+ fh_lock(fhp);
- dchild = lookup_one_len(fname, dentry, flen);
- err = PTR_ERR(dchild);
- if (IS_ERR(dchild))
- goto out_nfserr;
-+ resfhp->fh_dentry = NULL;
- err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
- if (err)
- goto out;
-@@ -870,10 +1032,12 @@
- * Make sure the child dentry is still negative ...
- */
- err = nfserr_exist;
-- if (dchild->d_inode) {
-- dprintk("nfsd_create: dentry %s/%s not negative!\n",
-- dentry->d_name.name, dchild->d_name.name);
-- goto out;
-+ if ( error == -EOPNOTSUPP) {
-+ if (dchild->d_inode) {
-+ dprintk("nfsd_create: dentry %s/%s not negative!\n",
-+ dentry->d_name.name, dchild->d_name.name);
-+ goto out;
-+ }
- }
-
- if (!(iap->ia_valid & ATTR_MODE))
-@@ -886,16 +1050,19 @@
- err = nfserr_perm;
- switch (type) {
- case S_IFREG:
-- err = vfs_create(dirp, dchild, iap->ia_mode);
-+ if (error == -EOPNOTSUPP)
-+ err = vfs_create(dirp, dchild, iap->ia_mode);
- break;
- case S_IFDIR:
-- err = vfs_mkdir(dirp, dchild, iap->ia_mode);
-+ if (error == -EOPNOTSUPP)
-+ err = vfs_mkdir(dirp, dchild, iap->ia_mode);
- break;
- case S_IFCHR:
- case S_IFBLK:
- case S_IFIFO:
- case S_IFSOCK:
-- err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
-+ if (error == -EOPNOTSUPP)
-+ err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
- break;
- default:
- printk("nfsd: bad file type %o in nfsd_create\n", type);
-@@ -964,7 +1131,13 @@
- /* 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->mknod_raw) {
-+ err = mknod_raw(dentry, fname, flen, iap->ia_mode, 0);
-+ if (err && err != -EOPNOTSUPP)
-+ goto out;
-+ }
-+
-+ if(!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it))
- goto out;
- fh_lock(fhp);
-
-@@ -1015,6 +1188,8 @@
- case NFS3_CREATE_GUARDED:
- err = nfserr_exist;
- }
-+ if(dirp->i_op->mknod_raw)
-+ err = 0;
- goto out;
- }
-
-@@ -1121,7 +1296,7 @@
- struct iattr *iap)
- {
- struct dentry *dentry, *dnew;
-- int err, cerr;
-+ int err, cerr, error = -EOPNOTSUPP;
-
- err = nfserr_noent;
- if (!flen || !plen)
-@@ -1135,12 +1310,18 @@
- goto out;
- fh_lock(fhp);
- dentry = fhp->fh_dentry;
-+
-+ if (dentry->d_inode->i_op->symlink_raw)
-+ error = symlink_raw(dentry, fname, flen, path);
-+
- dnew = lookup_one_len(fname, dentry, flen);
- err = PTR_ERR(dnew);
- if (IS_ERR(dnew))
- goto out_nfserr;
-
-- err = vfs_symlink(dentry->d_inode, dnew, path);
-+ err = error;
-+ if (err == -EOPNOTSUPP || !dentry->d_inode->i_op->symlink_raw)
-+ err = vfs_symlink(dentry->d_inode, dnew, path);
- if (!err) {
- if (EX_ISSYNC(fhp->fh_export))
- nfsd_sync_dir(dentry);
-@@ -1150,7 +1331,10 @@
- iap->ia_valid |= ATTR_CTIME;
- iap->ia_mode = (iap->ia_mode&S_IALLUGO)
- | S_IFLNK;
-- err = notify_change(dnew, iap);
-+ if (dnew->d_inode->i_op && dnew->d_inode->i_op->setattr_raw)
-+ err = setattr_raw(dnew->d_inode, iap);
-+ else
-+ err = notify_change(dnew, iap);
- if (err)
- err = nfserrno(err);
- else if (EX_ISSYNC(fhp->fh_export))
-@@ -1210,7 +1394,10 @@
- dold = tfhp->fh_dentry;
- dest = dold->d_inode;
-
-- err = vfs_link(dold, dirp, dnew);
-+ if (dirp->i_op->link_raw)
-+ err = link_raw(dold, ddir, dnew);
-+ else
-+ err = vfs_link(dold, dirp, dnew);
- if (!err) {
- if (EX_ISSYNC(ffhp->fh_export)) {
- nfsd_sync_dir(ddir);
-@@ -1295,7 +1482,10 @@
- err = nfserr_perm;
- } else
- #endif
-- err = vfs_rename(fdir, odentry, tdir, ndentry);
-+ if(fdir->i_op->rename_raw)
-+ err = rename_raw(fdentry, tdentry, odentry, ndentry);
-+ else
-+ err = vfs_rename(fdir, odentry, tdir, ndentry);
- if (!err && EX_ISSYNC(tfhp->fh_export)) {
- nfsd_sync_dir(tdentry);
- nfsd_sync_dir(fdentry);
-@@ -1316,7 +1506,7 @@
- fill_post_wcc(tfhp);
- double_up(&tdir->i_sem, &fdir->i_sem);
- ffhp->fh_locked = tfhp->fh_locked = 0;
--
-+
- out:
- return err;
- }
-@@ -1362,9 +1552,15 @@
- err = nfserr_perm;
- } else
- #endif
-- err = vfs_unlink(dirp, rdentry);
-+ if (dirp->i_op->unlink_raw)
-+ err = unlink_raw(dentry, fname, flen, rdentry);
-+ else
-+ err = vfs_unlink(dirp, rdentry);
- } else { /* It's RMDIR */
-- err = vfs_rmdir(dirp, rdentry);
-+ if (dirp->i_op->rmdir_raw)
-+ err = rmdir_raw(dentry, fname, flen, rdentry);
-+ else
-+ err = vfs_rmdir(dirp, rdentry);
- }
-
- dput(rdentry);
-Index: lum/include/linux/fs.h
-===================================================================
---- lum.orig/include/linux/fs.h 2004-06-07 17:25:22.000000000 -0400
-+++ lum/include/linux/fs.h 2004-06-07 17:25:22.000000000 -0400
-@@ -93,6 +93,9 @@
- #define FS_SINGLE 8 /* Filesystem that can have only one superblock */
- #define FS_NOMOUNT 16 /* Never mount from userland */
- #define FS_LITTER 32 /* Keeps the tree in dcache */
-+#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for
-+ * exporting non device filesystems.
-+ */
- #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon
- * as nfs_rename() will be cleaned up
- */
-@@ -1122,6 +1125,9 @@
- struct nameidata *nd, struct lookup_intent *it);
- extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
- int flags, struct lookup_intent *it);
-+extern int revalidate_it(struct dentry *dentry, struct lookup_intent *it);
-+extern int init_private_file_it(struct file *, struct dentry *dentry, int mode,
-+ struct lookup_intent *it);
- extern int filp_close(struct file *, fl_owner_t id);
- extern char * getname(const char *);
-
-@@ -1419,6 +1425,8 @@
- extern int follow_down(struct vfsmount **, struct dentry **);
- extern int follow_up(struct vfsmount **, struct dentry **);
- extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
-+extern struct dentry * lookup_one_len_it(const char *, struct dentry *, int,
-+ struct lookup_intent *);
- extern struct dentry * lookup_hash(struct qstr *, struct dentry *, struct nameidata *);
- #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
- #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
-@@ -1434,6 +1442,8 @@
-
- typedef int (*find_inode_t)(struct inode *, unsigned long, void *);
- extern struct inode * iget4(struct super_block *, unsigned long, find_inode_t, void *);
-+extern struct inode * ilookup4(struct super_block *, unsigned long,
-+ find_inode_t, void *);
- static inline struct inode *iget(struct super_block *sb, unsigned long ino)
- {
- return iget4(sb, ino, NULL, NULL);
-Index: lum/kernel/ksyms.c
-===================================================================
---- lum.orig/kernel/ksyms.c 2004-06-07 17:25:22.000000000 -0400
-+++ lum/kernel/ksyms.c 2004-06-07 17:25:22.000000000 -0400
-@@ -150,6 +150,7 @@
- EXPORT_SYMBOL(iunique);
- EXPORT_SYMBOL(ilookup);
- EXPORT_SYMBOL(iget4);
-+EXPORT_SYMBOL(ilookup4);
- EXPORT_SYMBOL(iput);
- EXPORT_SYMBOL(inode_init_once);
- EXPORT_SYMBOL(force_delete);
-@@ -161,6 +162,7 @@
- EXPORT_SYMBOL(path_release);
- EXPORT_SYMBOL(__user_walk);
- EXPORT_SYMBOL(lookup_one_len);
-+EXPORT_SYMBOL(lookup_one_len_it);
- EXPORT_SYMBOL(lookup_hash);
- EXPORT_SYMBOL(sys_close);
- EXPORT_SYMBOL(dcache_lock);
+++ /dev/null
-Index: linux-2.4.18-chaos/include/linux/proc_fs.h
-===================================================================
---- linux-2.4.18-chaos.orig/include/linux/proc_fs.h 2003-07-28 17:52:18.000000000 +0400
-+++ linux-2.4.18-chaos/include/linux/proc_fs.h 2004-01-12 20:12:38.000000000 +0300
-@@ -25,7 +25,7 @@
- /* Finally, the dynamically allocatable proc entries are reserved: */
-
- #define PROC_DYNAMIC_FIRST 4096
--#define PROC_NDYNAMIC 4096
-+#define PROC_NDYNAMIC 16384
-
- #define PROC_SUPER_MAGIC 0x9fa0
-
+++ /dev/null
- include/linux/skbuff.h | 30 +++++
- include/net/tcp.h | 5
- net/core/skbuff.c | 25 ++++
- net/ipv4/tcp.c | 252 ++++++++++++++++++++++++++++++++++++++++++++++++-
- net/netsyms.c | 2
- 5 files changed, 311 insertions(+), 3 deletions(-)
-
-Index: linux-2.4.22-vanilla/include/linux/skbuff.h
-===================================================================
---- linux-2.4.22-vanilla.orig/include/linux/skbuff.h 2003-11-03 23:22:13.000000000 +0300
-+++ linux-2.4.22-vanilla/include/linux/skbuff.h 2003-12-02 23:56:35.000000000 +0300
-@@ -116,6 +116,30 @@
- __u16 size;
- };
-
-+/* Support for callback when skb data has been released */
-+typedef struct zccd /* Zero Copy Callback Descriptor */
-+{ /* (embed as first member of custom struct) */
-+ atomic_t zccd_count; /* reference count */
-+ void (*zccd_destructor)(struct zccd *); /* callback when refcount reaches zero */
-+} zccd_t;
-+
-+static inline void zccd_init (zccd_t *d, void (*callback)(zccd_t *))
-+{
-+ atomic_set (&d->zccd_count, 1);
-+ d->zccd_destructor = callback;
-+}
-+
-+static inline void zccd_get (zccd_t *d) /* take a reference */
-+{
-+ atomic_inc (&d->zccd_count);
-+}
-+
-+static inline void zccd_put (zccd_t *d) /* release a reference */
-+{
-+ if (atomic_dec_and_test (&d->zccd_count))
-+ (d->zccd_destructor)(d);
-+}
-+
- /* This data is invariant across clones and lives at
- * the end of the header data, ie. at skb->end.
- */
-@@ -123,6 +147,12 @@
- atomic_t dataref;
- unsigned int nr_frags;
- struct sk_buff *frag_list;
-+ zccd_t *zccd; /* zero copy descriptor */
-+ zccd_t *zccd2; /* 2nd zero copy descriptor */
-+ /* NB we expect zero-copy data to be at least 1 packet, so
-+ * having 2 zccds means we don't unneccessarily split the packet
-+ * where consecutive zero-copy sends abutt.
-+ */
- skb_frag_t frags[MAX_SKB_FRAGS];
- };
-
-Index: linux-2.4.22-vanilla/include/net/tcp.h
-===================================================================
---- linux-2.4.22-vanilla.orig/include/net/tcp.h 2003-11-03 23:22:13.000000000 +0300
-+++ linux-2.4.22-vanilla/include/net/tcp.h 2003-12-02 23:58:10.000000000 +0300
-@@ -643,6 +643,8 @@
-
- extern int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int size);
- extern ssize_t tcp_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags);
-+extern ssize_t tcp_sendpage_zccd(struct socket *sock, struct page *page, int offset, size_t size,
-+ int flags, zccd_t *zccd);
-
- extern int tcp_ioctl(struct sock *sk,
- int cmd,
-@@ -737,6 +739,9 @@
- struct msghdr *msg,
- int len, int nonblock,
- int flags, int *addr_len);
-+extern int tcp_recvpackets(struct sock *sk,
-+ struct sk_buff_head *packets,
-+ int len, int nonblock);
-
- extern int tcp_listen_start(struct sock *sk);
-
-Index: linux-2.4.22-vanilla/net/core/skbuff.c
-===================================================================
---- linux-2.4.22-vanilla.orig/net/core/skbuff.c 2003-11-03 23:22:13.000000000 +0300
-+++ linux-2.4.22-vanilla/net/core/skbuff.c 2003-12-02 23:56:15.000000000 +0300
-@@ -208,6 +208,8 @@
- atomic_set(&(skb_shinfo(skb)->dataref), 1);
- skb_shinfo(skb)->nr_frags = 0;
- skb_shinfo(skb)->frag_list = NULL;
-+ skb_shinfo(skb)->zccd = NULL; /* skbuffs kick off with NO user zero copy descriptors */
-+ skb_shinfo(skb)->zccd2 = NULL;
- return skb;
-
- nodata:
-@@ -277,6 +279,10 @@
- {
- if (!skb->cloned ||
- atomic_dec_and_test(&(skb_shinfo(skb)->dataref))) {
-+ if (skb_shinfo(skb)->zccd != NULL) /* zero copy callback descriptor? */
-+ zccd_put (skb_shinfo(skb)->zccd); /* release hold */
-+ if (skb_shinfo(skb)->zccd2 != NULL) /* 2nd zero copy callback descriptor? */
-+ zccd_put (skb_shinfo(skb)->zccd2); /* release hold */
- if (skb_shinfo(skb)->nr_frags) {
- int i;
- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
-@@ -535,6 +541,8 @@
- atomic_set(&(skb_shinfo(skb)->dataref), 1);
- skb_shinfo(skb)->nr_frags = 0;
- skb_shinfo(skb)->frag_list = NULL;
-+ skb_shinfo(skb)->zccd = NULL; /* copied data => no user zero copy descriptor */
-+ skb_shinfo(skb)->zccd2 = NULL;
-
- /* We are no longer a clone, even if we were. */
- skb->cloned = 0;
-@@ -581,6 +589,14 @@
- n->data_len = skb->data_len;
- n->len = skb->len;
-
-+ if (skb_shinfo(skb)->zccd != NULL) /* user zero copy descriptor? */
-+ zccd_get (skb_shinfo(skb)->zccd); /* 1 more ref (pages are shared) */
-+ skb_shinfo(n)->zccd = skb_shinfo(skb)->zccd;
-+
-+ if (skb_shinfo(skb)->zccd2 != NULL) /* 2nd user zero copy descriptor? */
-+ zccd_get (skb_shinfo(skb)->zccd2); /* 1 more ref (pages are shared) */
-+ skb_shinfo(n)->zccd2 = skb_shinfo(skb)->zccd2;
-+
- if (skb_shinfo(skb)->nr_frags) {
- int i;
-
-@@ -623,6 +639,8 @@
- u8 *data;
- int size = nhead + (skb->end - skb->head) + ntail;
- long off;
-+ zccd_t *zccd = skb_shinfo(skb)->zccd; /* stash user zero copy descriptor */
-+ zccd_t *zccd2 = skb_shinfo(skb)->zccd2; /* stash 2nd user zero copy descriptor */
-
- if (skb_shared(skb))
- BUG();
-@@ -644,6 +662,11 @@
- if (skb_shinfo(skb)->frag_list)
- skb_clone_fraglist(skb);
-
-+ if (zccd != NULL) /* user zero copy descriptor? */
-+ zccd_get (zccd); /* extra ref (pages are shared) */
-+ if (zccd2 != NULL) /* 2nd user zero copy descriptor? */
-+ zccd_get (zccd2); /* extra ref (pages are shared) */
-+
- skb_release_data(skb);
-
- off = (data+nhead) - skb->head;
-@@ -658,6 +681,8 @@
- skb->nh.raw += off;
- skb->cloned = 0;
- atomic_set(&skb_shinfo(skb)->dataref, 1);
-+ skb_shinfo(skb)->zccd = zccd;
-+ skb_shinfo(skb)->zccd2 = zccd2;
- return 0;
-
- nodata:
-Index: linux-2.4.22-vanilla/net/ipv4/tcp.c
-===================================================================
---- linux-2.4.22-vanilla.orig/net/ipv4/tcp.c 2003-11-03 23:22:13.000000000 +0300
-+++ linux-2.4.22-vanilla/net/ipv4/tcp.c 2003-12-02 23:56:15.000000000 +0300
-@@ -747,7 +747,7 @@
- goto out;
- }
-
--ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset, size_t psize, int flags);
-+ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset, size_t psize, int flags, zccd_t *zccd);
-
- static inline int
- can_coalesce(struct sk_buff *skb, int i, struct page *page, int off)
-@@ -826,7 +826,8 @@
- return err;
- }
-
--ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset, size_t psize, int flags)
-+/* Extra parameter: user zero copy descriptor (or NULL if not doing that) */
-+ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset, size_t psize, int flags, zccd_t *zccd)
- {
- struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
- int mss_now;
-@@ -874,6 +875,17 @@
- copy = size;
-
- i = skb_shinfo(skb)->nr_frags;
-+
-+ if (zccd != NULL && /* this is a zcc I/O */
-+ skb_shinfo(skb)->zccd != NULL && /* skb is part of a zcc I/O */
-+ skb_shinfo(skb)->zccd2 != NULL &&
-+ skb_shinfo(skb)->zccd != zccd && /* not the same one */
-+ skb_shinfo(skb)->zccd2 != zccd)
-+ {
-+ tcp_mark_push (tp, skb);
-+ goto new_segment;
-+ }
-+
- if (can_coalesce(skb, i, page, offset)) {
- skb_shinfo(skb)->frags[i-1].size += copy;
- } else if (i < MAX_SKB_FRAGS) {
-@@ -884,6 +896,20 @@
- goto new_segment;
- }
-
-+ if (zccd != NULL && /* this is a zcc I/O */
-+ skb_shinfo(skb)->zccd != zccd && /* not already referencing this zccd */
-+ skb_shinfo(skb)->zccd2 != zccd)
-+ {
-+ zccd_get (zccd); /* bump ref count */
-+
-+ BUG_TRAP (skb_shinfo(skb)->zccd2 == NULL);
-+
-+ if (skb_shinfo(skb)->zccd == NULL) /* reference this zccd */
-+ skb_shinfo(skb)->zccd = zccd;
-+ else
-+ skb_shinfo(skb)->zccd2 = zccd;
-+ }
-+
- skb->len += copy;
- skb->data_len += copy;
- skb->ip_summed = CHECKSUM_HW;
-@@ -947,7 +973,31 @@
-
- lock_sock(sk);
- TCP_CHECK_TIMER(sk);
-- res = do_tcp_sendpages(sk, &page, offset, size, flags);
-+ res = do_tcp_sendpages(sk, &page, offset, size, flags, NULL);
-+ TCP_CHECK_TIMER(sk);
-+ release_sock(sk);
-+ return res;
-+}
-+
-+ssize_t tcp_sendpage_zccd(struct socket *sock, struct page *page, int offset, size_t size,
-+ int flags, zccd_t *zccd)
-+{
-+ ssize_t res;
-+ struct sock *sk = sock->sk;
-+
-+#define TCP_ZC_CSUM_FLAGS (NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM)
-+
-+ if (!(sk->route_caps & NETIF_F_SG) || /* caller shouldn't waste her time */
-+ !(sk->route_caps & TCP_ZC_CSUM_FLAGS)) /* on double mapping */
-+ BUG ();
-+
-+#undef TCP_ZC_CSUM_FLAGS
-+
-+ lock_sock(sk);
-+ TCP_CHECK_TIMER(sk);
-+
-+ res = do_tcp_sendpages(sk, &page, offset, size, flags, zccd);
-+
- TCP_CHECK_TIMER(sk);
- release_sock(sk);
- return res;
-@@ -1771,6 +1821,202 @@
- goto out;
- }
-
-+int tcp_recvpackets (struct sock *sk, struct sk_buff_head *packets,
-+ int len, int nonblock)
-+{
-+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
-+ int copied;
-+ long timeo;
-+
-+ BUG_TRAP (len > 0);
-+ /*BUG_TRAP ((flags & (MSG_OOB | MSG_PEEK | MSG_TRUNC)) == 0);*/
-+
-+ lock_sock(sk);
-+
-+ TCP_CHECK_TIMER(sk);
-+
-+ copied = -ENOTCONN;
-+ if (sk->state == TCP_LISTEN)
-+ goto out;
-+
-+ copied = 0;
-+ timeo = sock_rcvtimeo(sk, nonblock);
-+
-+ do {
-+ struct sk_buff * skb;
-+ u32 offset;
-+ unsigned long used;
-+ int exhausted;
-+ int eaten;
-+
-+ /* Are we at urgent data? Stop if we have read anything. */
-+ if (copied && tp->urg_data && tp->urg_seq == tp->copied_seq)
-+ break;
-+
-+ /* We need to check signals first, to get correct SIGURG
-+ * handling. FIXME: Need to check this doesnt impact 1003.1g
-+ * and move it down to the bottom of the loop
-+ */
-+ if (signal_pending(current)) {
-+ if (copied)
-+ break;
-+ copied = timeo ? sock_intr_errno(timeo) : -EAGAIN;
-+ break;
-+ }
-+
-+ /* Next get a buffer. */
-+
-+ skb = skb_peek(&sk->receive_queue);
-+
-+ if (skb == NULL) /* nothing ready */
-+ {
-+ if (copied) {
-+ if (sk->err ||
-+ sk->state == TCP_CLOSE ||
-+ (sk->shutdown & RCV_SHUTDOWN) ||
-+ !timeo ||
-+ (0))
-+ break;
-+ } else {
-+ if (sk->done)
-+ break;
-+
-+ if (sk->err) {
-+ copied = sock_error(sk);
-+ break;
-+ }
-+
-+ if (sk->shutdown & RCV_SHUTDOWN)
-+ break;
-+
-+ if (sk->state == TCP_CLOSE) {
-+ if (!sk->done) {
-+ /* This occurs when user tries to read
-+ * from never connected socket.
-+ */
-+ copied = -ENOTCONN;
-+ break;
-+ }
-+ break;
-+ }
-+
-+ if (!timeo) {
-+ copied = -EAGAIN;
-+ break;
-+ }
-+ }
-+
-+ cleanup_rbuf(sk, copied);
-+ timeo = tcp_data_wait(sk, timeo);
-+ continue;
-+ }
-+
-+ BUG_TRAP (atomic_read (&skb->users) == 1);
-+
-+ exhausted = eaten = 0;
-+
-+ offset = tp->copied_seq - TCP_SKB_CB(skb)->seq;
-+ if (skb->h.th->syn)
-+ offset--;
-+
-+ used = skb->len - offset;
-+
-+ if (tp->urg_data) {
-+ u32 urg_offset = tp->urg_seq - tp->copied_seq;
-+ if (urg_offset < used) {
-+ if (!urg_offset) { /* at urgent date */
-+ if (!sk->urginline) {
-+ tp->copied_seq++; /* discard the single byte of urgent data */
-+ offset++;
-+ used--;
-+ }
-+ } else /* truncate read */
-+ used = urg_offset;
-+ }
-+ }
-+
-+ BUG_TRAP (used >= 0);
-+ if (len < used)
-+ used = len;
-+
-+ if (used == 0)
-+ exhausted = 1;
-+ else
-+ {
-+ if (skb_is_nonlinear (skb))
-+ {
-+ int rc = skb_linearize (skb, GFP_KERNEL);
-+
-+ printk ("tcp_recvpackets(): linearising: %d\n", rc);
-+
-+ if (rc)
-+ {
-+ if (!copied)
-+ copied = rc;
-+ break;
-+ }
-+ }
-+
-+ if ((offset + used) == skb->len) /* consuming the whole packet */
-+ {
-+ __skb_unlink (skb, &sk->receive_queue);
-+ dst_release (skb->dst);
-+ skb_orphan (skb);
-+ __skb_pull (skb, offset);
-+ __skb_queue_tail (packets, skb);
-+ exhausted = eaten = 1;
-+ }
-+ else /* consuming only part of the packet */
-+ {
-+ struct sk_buff *skb2 = skb_clone (skb, GFP_KERNEL);
-+
-+ if (skb2 == NULL)
-+ {
-+ if (!copied)
-+ copied = -ENOMEM;
-+ break;
-+ }
-+
-+ dst_release (skb2->dst);
-+ __skb_pull (skb2, offset);
-+ __skb_trim (skb2, used);
-+ __skb_queue_tail (packets, skb2);
-+ }
-+
-+ tp->copied_seq += used;
-+ copied += used;
-+ len -= used;
-+ }
-+
-+ if (tp->urg_data && after(tp->copied_seq,tp->urg_seq)) {
-+ tp->urg_data = 0;
-+ tcp_fast_path_check(sk, tp);
-+ }
-+
-+ if (!exhausted)
-+ continue;
-+
-+ if (skb->h.th->fin)
-+ {
-+ tp->copied_seq++;
-+ if (!eaten)
-+ tcp_eat_skb (sk, skb);
-+ break;
-+ }
-+
-+ if (!eaten)
-+ tcp_eat_skb (sk, skb);
-+
-+ } while (len > 0);
-+
-+ out:
-+ /* Clean up data we have read: This will do ACK frames. */
-+ cleanup_rbuf(sk, copied);
-+ TCP_CHECK_TIMER(sk);
-+ release_sock(sk);
-+ return copied;
-+}
-+
- /*
- * State processing on a close. This implements the state shift for
- * sending our FIN frame. Note that we only send a FIN for some
-Index: linux-2.4.22-vanilla/net/netsyms.c
-===================================================================
---- linux-2.4.22-vanilla.orig/net/netsyms.c 2003-11-03 23:22:13.000000000 +0300
-+++ linux-2.4.22-vanilla/net/netsyms.c 2003-12-04 20:42:50.000000000 +0300
-@@ -417,6 +417,8 @@
-
- #endif
-
-+EXPORT_SYMBOL(tcp_sendpage_zccd);
-+EXPORT_SYMBOL(tcp_recvpackets);
- EXPORT_SYMBOL(tcp_read_sock);
-
- EXPORT_SYMBOL(netlink_set_err);
+++ /dev/null
---- linux-2.4.20-vanilla/arch/i386/kernel/sys_i386.c~uml-2.4.20-do_mmap_pgoff-fix 2001-03-19 23:35:09.000000000 +0300
-+++ linux-2.4.20-vanilla-alexey/arch/i386/kernel/sys_i386.c 2003-09-15 10:26:19.000000000 +0400
-@@ -56,7 +56,7 @@ static inline long do_mmap2(
- }
-
- down_write(¤t->mm->mmap_sem);
-- error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-+ error = do_mmap_pgoff(current->mm, file, addr, len, prot, flags, pgoff);
- up_write(¤t->mm->mmap_sem);
-
- if (file)
---- linux-2.4.24-vanilla/arch/x86_64/kernel/sys_x86_64.c 2004-10-15 12:19:54.919366416 -0400
-+++ linux-2.4.24-vanilla-x86_64/arch/x86_64/kernel/sys_x86_64.c 2003-11-28 13:26:19.000000000 -0500
-@@ -56,7 +56,7 @@
- }
-
- down_write(¤t->mm->mmap_sem);
-- error = do_mmap_pgoff(file, addr, len, prot, flags, off >> PAGE_SHIFT);
-+ error = do_mmap_pgoff(current->mm, file, addr, len, prot, flags, off >> PAGE_SHIFT);
- up_write(¤t->mm->mmap_sem);
-
- if (file)
---- linux-2.4.24-vanilla/arch/x86_64/ia32/sys_ia32.c 2003-11-28 13:26:19.000000000 -0500
-+++ linux-2.4.24-vanilla-x86_64/arch/x86_64/ia32/sys_ia32.c 2004-10-15 12:36:52.114075768 -0400
-@@ -335,7 +335,7 @@
-
- mm = current->mm;
- down_write(&mm->mmap_sem);
-- retval = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, a.offset>>PAGE_SHIFT);
-+ retval = do_mmap_pgoff(current->mm, file, a.addr, a.len, a.prot, a.flags, a.offset>>PAGE_SHIFT);
- if (file)
- fput(file);
-
-@@ -2111,7 +2111,7 @@
- prot |= PROT_EXEC;
-
- down_write(&mm->mmap_sem);
-- error = do_mmap_pgoff(file, addr, len, prot, flags|MAP_32BIT, pgoff);
-+ error = do_mmap_pgoff(current->mm, file, addr, len, prot, flags|MAP_32BIT, pgoff);
- up_write(&mm->mmap_sem);
-
- if (file)
+++ /dev/null
-Index: linux-2.4.24-vanilla/arch/um/kernel/ksyms.c
-===================================================================
---- linux-2.4.24-vanilla.orig/arch/um/kernel/ksyms.c 2004-01-10 17:47:10.000000000 +0300
-+++ linux-2.4.24-vanilla/arch/um/kernel/ksyms.c 2004-01-10 18:22:30.000000000 +0300
-@@ -34,6 +34,7 @@
- EXPORT_SYMBOL(host_task_size);
- EXPORT_SYMBOL(arch_validate);
- EXPORT_SYMBOL(get_kmem_end);
-+EXPORT_SYMBOL(end_iomem);
-
- EXPORT_SYMBOL(high_physmem);
- EXPORT_SYMBOL(empty_zero_page);
+++ /dev/null
-diff -Naur -X ../exclude-files orig/arch/um/common.ld.in um/arch/um/common.ld.in
---- orig/arch/um/common.ld.in 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/common.ld.in 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,53 @@
-+ .kstrtab : { *(.kstrtab) }
-+
-+ . = ALIGN(16); /* Exception table */
-+ __start___ex_table = .;
-+ __ex_table : { *(__ex_table) }
-+ __stop___ex_table = .;
-+
-+ __start___ksymtab = .; /* Kernel symbol table */
-+ __ksymtab : { *(__ksymtab) }
-+ __stop___ksymtab = .;
-+
-+ .unprotected : { *(.unprotected) }
-+ . = ALIGN(4096);
-+ PROVIDE (_unprotected_end = .);
-+
-+ . = ALIGN(4096);
-+ __uml_setup_start = .;
-+ .uml.setup.init : { *(.uml.setup.init) }
-+ __uml_setup_end = .;
-+ __uml_help_start = .;
-+ .uml.help.init : { *(.uml.help.init) }
-+ __uml_help_end = .;
-+ __uml_postsetup_start = .;
-+ .uml.postsetup.init : { *(.uml.postsetup.init) }
-+ __uml_postsetup_end = .;
-+ __setup_start = .;
-+ .setup.init : { *(.setup.init) }
-+ __setup_end = .;
-+ __initcall_start = .;
-+ .initcall.init : { *(.initcall.init) }
-+ __initcall_end = .;
-+ __uml_initcall_start = .;
-+ .uml.initcall.init : { *(.uml.initcall.init) }
-+ __uml_initcall_end = .;
-+ __init_end = .;
-+ __exitcall_begin = .;
-+ .exitcall : { *(.exitcall.exit) }
-+ __exitcall_end = .;
-+ __uml_exitcall_begin = .;
-+ .uml.exitcall : { *(.uml.exitcall.exit) }
-+ __uml_exitcall_end = .;
-+
-+ __preinit_array_start = .;
-+ .preinit_array : { *(.preinit_array) }
-+ __preinit_array_end = .;
-+ __init_array_start = .;
-+ .init_array : { *(.init_array) }
-+ __init_array_end = .;
-+ __fini_array_start = .;
-+ .fini_array : { *(.fini_array) }
-+ __fini_array_end = .;
-+
-+ .data.init : { *(.data.init) }
-diff -Naur -X ../exclude-files orig/arch/um/config_block.in um/arch/um/config_block.in
---- orig/arch/um/config_block.in 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/config_block.in 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,22 @@
-+mainmenu_option next_comment
-+comment 'Block Devices'
-+
-+bool 'Virtual block device' CONFIG_BLK_DEV_UBD
-+dep_bool ' Always do synchronous disk IO for UBD' CONFIG_BLK_DEV_UBD_SYNC $CONFIG_BLK_DEV_UBD
-+bool 'COW device' CONFIG_COW
-+
-+if [ "$CONFIG_BLK_DEV_UBD" = "y" -o "$CONFIG_COW" = "y" ] ; then
-+ define_bool CONFIG_COW_COMMON y
-+fi
-+
-+tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
-+dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET
-+tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
-+if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then
-+ int ' Default RAM disk size' CONFIG_BLK_DEV_RAM_SIZE 4096
-+fi
-+dep_bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM
-+
-+tristate 'Example IO memory driver' CONFIG_MMAPPER
-+
-+endmenu
-diff -Naur -X ../exclude-files orig/arch/um/config_char.in um/arch/um/config_char.in
---- orig/arch/um/config_char.in 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/config_char.in 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,37 @@
-+mainmenu_option next_comment
-+comment 'Character Devices'
-+
-+define_bool CONFIG_STDIO_CONSOLE y
-+
-+bool 'Virtual serial line' CONFIG_SSL
-+
-+bool 'file descriptor channel support' CONFIG_FD_CHAN
-+bool 'null channel support' CONFIG_NULL_CHAN
-+bool 'port channel support' CONFIG_PORT_CHAN
-+bool 'pty channel support' CONFIG_PTY_CHAN
-+bool 'tty channel support' CONFIG_TTY_CHAN
-+bool 'xterm channel support' CONFIG_XTERM_CHAN
-+string 'Default main console channel initialization' CONFIG_CON_ZERO_CHAN \
-+ "fd:0,fd:1"
-+string 'Default console channel initialization' CONFIG_CON_CHAN "xterm"
-+string 'Default serial line channel initialization' CONFIG_SSL_CHAN "pty"
-+
-+
-+bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
-+if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
-+ int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
-+fi
-+
-+bool 'Watchdog Timer Support' CONFIG_WATCHDOG
-+dep_bool ' Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT \
-+ $CONFIG_WATCHDOG
-+dep_tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG $CONFIG_WATCHDOG
-+dep_tristate ' UML watchdog' CONFIG_UML_WATCHDOG $CONFIG_WATCHDOG
-+
-+tristate 'Sound support' CONFIG_UML_SOUND
-+define_tristate CONFIG_SOUND $CONFIG_UML_SOUND
-+define_tristate CONFIG_HOSTAUDIO $CONFIG_UML_SOUND
-+
-+bool 'Enable tty logging' CONFIG_TTY_LOG
-+
-+endmenu
-diff -Naur -X ../exclude-files orig/arch/um/config.in um/arch/um/config.in
---- orig/arch/um/config.in 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/config.in 2003-12-14 11:34:02.000000000 -0500
-@@ -0,0 +1,105 @@
-+define_bool CONFIG_USERMODE y
-+
-+mainmenu_name "Linux/Usermode Kernel Configuration"
-+
-+define_bool CONFIG_ISA n
-+define_bool CONFIG_SBUS n
-+define_bool CONFIG_PCI n
-+
-+define_bool CONFIG_UID16 y
-+
-+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
-+
-+mainmenu_option next_comment
-+comment 'Code maturity level options'
-+bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
-+endmenu
-+
-+mainmenu_option next_comment
-+comment 'General Setup'
-+
-+bool 'Separate kernel address space support' CONFIG_MODE_SKAS
-+
-+# This is to ensure that at least one of the modes is enabled. When neither
-+# is present in defconfig, they default to N, which is bad.
-+if [ "$CONFIG_MODE_SKAS" != "y" ]; then
-+ define_bool CONFIG_MODE_TT y
-+fi
-+
-+bool 'Tracing thread support' CONFIG_MODE_TT
-+if [ "$CONFIG_MODE_TT" != "y" ]; then
-+ bool 'Statically linked binary when CONFIG_MODE_TT is disabled' CONFIG_STATIC_LINK
-+fi
-+bool 'Networking support' CONFIG_NET
-+bool 'System V IPC' CONFIG_SYSVIPC
-+bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
-+bool 'Sysctl support' CONFIG_SYSCTL
-+tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
-+tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
-+tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
-+tristate 'Host filesystem' CONFIG_HOSTFS
-+tristate 'Honeypot proc filesystem' CONFIG_HPPFS
-+bool 'Management console' CONFIG_MCONSOLE
-+dep_bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ $CONFIG_MCONSOLE
-+bool '2G/2G host address space split' CONFIG_HOST_2G_2G
-+bool 'Symmetric multi-processing support' CONFIG_UML_SMP
-+define_bool CONFIG_SMP $CONFIG_UML_SMP
-+int 'Nesting level' CONFIG_NEST_LEVEL 0
-+int 'Kernel address space size (in .5G units)' CONFIG_KERNEL_HALF_GIGS 1
-+bool 'Highmem support' CONFIG_HIGHMEM
-+bool '/proc/mm' CONFIG_PROC_MM
-+int 'Kernel stack size order' CONFIG_KERNEL_STACK_ORDER 2
-+bool 'Real-time Clock' CONFIG_UML_REAL_TIME_CLOCK
-+endmenu
-+
-+mainmenu_option next_comment
-+comment 'Loadable module support'
-+bool 'Enable loadable module support' CONFIG_MODULES
-+if [ "$CONFIG_MODULES" = "y" ]; then
-+# MODVERSIONS does not yet work in this architecture
-+# bool ' Set version information on all module symbols' CONFIG_MODVERSIONS
-+ bool ' Kernel module loader' CONFIG_KMOD
-+fi
-+endmenu
-+
-+source arch/um/config_char.in
-+
-+source arch/um/config_block.in
-+
-+define_bool CONFIG_NETDEVICES $CONFIG_NET
-+
-+if [ "$CONFIG_NET" = "y" ]; then
-+ source arch/um/config_net.in
-+ source net/Config.in
-+fi
-+
-+source fs/Config.in
-+
-+mainmenu_option next_comment
-+comment 'SCSI support'
-+
-+tristate 'SCSI support' CONFIG_SCSI
-+
-+if [ "$CONFIG_SCSI" != "n" ]; then
-+ source arch/um/config_scsi.in
-+fi
-+endmenu
-+
-+source drivers/md/Config.in
-+
-+source drivers/mtd/Config.in
-+
-+source lib/Config.in
-+
-+mainmenu_option next_comment
-+comment 'Kernel hacking'
-+bool 'Debug memory allocations' CONFIG_DEBUG_SLAB
-+bool 'Enable kernel debugging symbols' CONFIG_DEBUGSYM
-+if [ "$CONFIG_XTERM_CHAN" = "y" ]; then
-+ dep_bool 'Enable ptrace proxy' CONFIG_PT_PROXY $CONFIG_DEBUGSYM
-+else
-+ define_bool CONFIG_PT_PROXY n
-+fi
-+dep_bool 'Enable gprof support' CONFIG_GPROF $CONFIG_DEBUGSYM
-+dep_bool 'Enable gcov support' CONFIG_GCOV $CONFIG_DEBUGSYM
-+endmenu
-diff -Naur -X ../exclude-files orig/arch/um/config_net.in um/arch/um/config_net.in
---- orig/arch/um/config_net.in 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/config_net.in 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,47 @@
-+mainmenu_option next_comment
-+comment 'Network Devices'
-+
-+# UML virtual driver
-+bool 'Virtual network device' CONFIG_UML_NET
-+
-+dep_bool ' Ethertap transport' CONFIG_UML_NET_ETHERTAP $CONFIG_UML_NET
-+dep_bool ' TUN/TAP transport' CONFIG_UML_NET_TUNTAP $CONFIG_UML_NET
-+dep_bool ' SLIP transport' CONFIG_UML_NET_SLIP $CONFIG_UML_NET
-+dep_bool ' SLiRP transport' CONFIG_UML_NET_SLIRP $CONFIG_UML_NET
-+dep_bool ' Daemon transport' CONFIG_UML_NET_DAEMON $CONFIG_UML_NET
-+dep_bool ' Multicast transport' CONFIG_UML_NET_MCAST $CONFIG_UML_NET
-+dep_bool ' pcap transport' CONFIG_UML_NET_PCAP $CONFIG_UML_NET
-+
-+# Below are hardware-independent drivers mirrored from
-+# drivers/net/Config.in. It would be nice if Linux
-+# had HW independent drivers separated from the other
-+# but it does not. Until then each non-ISA/PCI arch
-+# needs to provide it's own menu of network drivers
-+
-+tristate 'Dummy net driver support' CONFIG_DUMMY
-+tristate 'Bonding driver support' CONFIG_BONDING
-+tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER
-+tristate 'Universal TUN/TAP device driver support' CONFIG_TUN
-+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-+ if [ "$CONFIG_NETLINK" = "y" ]; then
-+ tristate 'Ethertap network tap (OBSOLETE)' CONFIG_ETHERTAP
-+ fi
-+fi
-+
-+tristate 'PPP (point-to-point protocol) support' CONFIG_PPP
-+if [ ! "$CONFIG_PPP" = "n" ]; then
-+ dep_bool ' PPP multilink support (EXPERIMENTAL)' CONFIG_PPP_MULTILINK $CONFIG_EXPERIMENTAL
-+ dep_bool ' PPP filtering' CONFIG_PPP_FILTER $CONFIG_FILTER
-+ dep_tristate ' PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP
-+ dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP
-+ dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP
-+ dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP $CONFIG_PPP
-+ dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP $CONFIG_EXPERIMENTAL
-+fi
-+
-+tristate 'SLIP (serial line) support' CONFIG_SLIP
-+dep_bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED $CONFIG_SLIP
-+dep_bool ' Keepalive and linefill' CONFIG_SLIP_SMART $CONFIG_SLIP
-+dep_bool ' Six bit SLIP encapsulation' CONFIG_SLIP_MODE_SLIP6 $CONFIG_SLIP
-+
-+endmenu
-diff -Naur -X ../exclude-files orig/arch/um/config.release um/arch/um/config.release
---- orig/arch/um/config.release 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/config.release 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,302 @@
-+#
-+# Automatically generated make config: don't edit
-+#
-+CONFIG_USERMODE=y
-+# CONFIG_ISA is not set
-+# CONFIG_SBUS is not set
-+# CONFIG_PCI is not set
-+CONFIG_UID16=y
-+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-+
-+#
-+# Code maturity level options
-+#
-+CONFIG_EXPERIMENTAL=y
-+
-+#
-+# General Setup
-+#
-+CONFIG_NET=y
-+CONFIG_SYSVIPC=y
-+CONFIG_BSD_PROCESS_ACCT=y
-+CONFIG_SYSCTL=y
-+CONFIG_BINFMT_AOUT=y
-+CONFIG_BINFMT_ELF=y
-+CONFIG_BINFMT_MISC=y
-+CONFIG_HOSTFS=y
-+# CONFIG_HPPFS is not set
-+CONFIG_MCONSOLE=y
-+CONFIG_MAGIC_SYSRQ=y
-+# CONFIG_HOST_2G_2G is not set
-+# CONFIG_UML_SMP is not set
-+# CONFIG_SMP is not set
-+CONFIG_NEST_LEVEL=0
-+CONFIG_KERNEL_HALF_GIGS=1
-+
-+#
-+# Loadable module support
-+#
-+CONFIG_MODULES=y
-+CONFIG_KMOD=y
-+
-+#
-+# Character Devices
-+#
-+CONFIG_STDIO_CONSOLE=y
-+CONFIG_SSL=y
-+CONFIG_FD_CHAN=y
-+# CONFIG_NULL_CHAN is not set
-+CONFIG_PORT_CHAN=y
-+CONFIG_PTY_CHAN=y
-+CONFIG_TTY_CHAN=y
-+CONFIG_XTERM_CHAN=y
-+CONFIG_CON_ZERO_CHAN="fd:0,fd:1"
-+CONFIG_CON_CHAN="xterm"
-+CONFIG_SSL_CHAN="pty"
-+CONFIG_UNIX98_PTYS=y
-+CONFIG_UNIX98_PTY_COUNT=256
-+# CONFIG_WATCHDOG is not set
-+CONFIG_UML_SOUND=y
-+CONFIG_SOUND=y
-+CONFIG_HOSTAUDIO=y
-+# CONFIG_TTY_LOG is not set
-+
-+#
-+# Block Devices
-+#
-+CONFIG_BLK_DEV_UBD=y
-+# CONFIG_BLK_DEV_UBD_SYNC is not set
-+CONFIG_BLK_DEV_LOOP=y
-+CONFIG_BLK_DEV_NBD=y
-+CONFIG_BLK_DEV_RAM=y
-+CONFIG_BLK_DEV_RAM_SIZE=4096
-+CONFIG_BLK_DEV_INITRD=y
-+# CONFIG_MMAPPER is not set
-+CONFIG_NETDEVICES=y
-+
-+#
-+# Network Devices
-+#
-+CONFIG_UML_NET=y
-+CONFIG_UML_NET_ETHERTAP=y
-+CONFIG_UML_NET_TUNTAP=y
-+CONFIG_UML_NET_SLIP=y
-+CONFIG_UML_NET_DAEMON=y
-+CONFIG_UML_NET_MCAST=y
-+CONFIG_DUMMY=y
-+CONFIG_BONDING=m
-+CONFIG_EQUALIZER=m
-+CONFIG_TUN=y
-+CONFIG_PPP=m
-+CONFIG_PPP_MULTILINK=y
-+# CONFIG_PPP_ASYNC is not set
-+CONFIG_PPP_SYNC_TTY=m
-+CONFIG_PPP_DEFLATE=m
-+CONFIG_PPP_BSDCOMP=m
-+CONFIG_PPPOE=m
-+CONFIG_SLIP=m
-+
-+#
-+# Networking options
-+#
-+CONFIG_PACKET=y
-+CONFIG_PACKET_MMAP=y
-+# CONFIG_NETLINK_DEV is not set
-+# CONFIG_NETFILTER is not set
-+# CONFIG_FILTER is not set
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+# CONFIG_IP_MULTICAST is not set
-+# CONFIG_IP_ADVANCED_ROUTER is not set
-+# CONFIG_IP_PNP is not set
-+# CONFIG_NET_IPIP is not set
-+# CONFIG_NET_IPGRE is not set
-+# CONFIG_ARPD is not set
-+# CONFIG_INET_ECN is not set
-+# CONFIG_SYN_COOKIES is not set
-+# CONFIG_IPV6 is not set
-+# CONFIG_KHTTPD is not set
-+# CONFIG_ATM is not set
-+# CONFIG_VLAN_8021Q is not set
-+
-+#
-+#
-+#
-+# CONFIG_IPX is not set
-+# CONFIG_ATALK is not set
-+
-+#
-+# Appletalk devices
-+#
-+# CONFIG_DECNET is not set
-+# CONFIG_BRIDGE is not set
-+# CONFIG_X25 is not set
-+# CONFIG_LAPB is not set
-+# CONFIG_LLC is not set
-+# CONFIG_NET_DIVERT is not set
-+# CONFIG_ECONET is not set
-+# CONFIG_WAN_ROUTER is not set
-+# CONFIG_NET_FASTROUTE is not set
-+# CONFIG_NET_HW_FLOWCONTROL is not set
-+
-+#
-+# QoS and/or fair queueing
-+#
-+# CONFIG_NET_SCHED is not set
-+
-+#
-+# Network testing
-+#
-+# CONFIG_NET_PKTGEN is not set
-+
-+#
-+# File systems
-+#
-+CONFIG_QUOTA=y
-+CONFIG_AUTOFS_FS=m
-+CONFIG_AUTOFS4_FS=m
-+CONFIG_REISERFS_FS=m
-+# CONFIG_REISERFS_CHECK is not set
-+# CONFIG_REISERFS_PROC_INFO is not set
-+CONFIG_ADFS_FS=m
-+# CONFIG_ADFS_FS_RW is not set
-+CONFIG_AFFS_FS=m
-+CONFIG_HFS_FS=m
-+CONFIG_BFS_FS=m
-+CONFIG_EXT3_FS=y
-+CONFIG_JBD=y
-+# CONFIG_JBD_DEBUG is not set
-+CONFIG_FAT_FS=y
-+CONFIG_MSDOS_FS=y
-+CONFIG_UMSDOS_FS=y
-+CONFIG_VFAT_FS=y
-+CONFIG_EFS_FS=m
-+CONFIG_CRAMFS=m
-+CONFIG_TMPFS=y
-+CONFIG_RAMFS=y
-+CONFIG_ISO9660_FS=y
-+# CONFIG_JOLIET is not set
-+# CONFIG_ZISOFS is not set
-+CONFIG_MINIX_FS=m
-+CONFIG_VXFS_FS=m
-+# CONFIG_NTFS_FS is not set
-+CONFIG_HPFS_FS=m
-+CONFIG_PROC_FS=y
-+CONFIG_DEVFS_FS=y
-+CONFIG_DEVFS_MOUNT=y
-+# CONFIG_DEVFS_DEBUG is not set
-+CONFIG_DEVPTS_FS=y
-+CONFIG_QNX4FS_FS=m
-+# CONFIG_QNX4FS_RW is not set
-+CONFIG_ROMFS_FS=m
-+CONFIG_EXT2_FS=y
-+CONFIG_SYSV_FS=m
-+CONFIG_UDF_FS=m
-+# CONFIG_UDF_RW is not set
-+CONFIG_UFS_FS=m
-+# CONFIG_UFS_FS_WRITE is not set
-+
-+#
-+# Network File Systems
-+#
-+# CONFIG_CODA_FS is not set
-+# CONFIG_INTERMEZZO_FS is not set
-+CONFIG_NFS_FS=y
-+CONFIG_NFS_V3=y
-+CONFIG_NFSD=y
-+CONFIG_NFSD_V3=y
-+CONFIG_SUNRPC=y
-+CONFIG_LOCKD=y
-+CONFIG_LOCKD_V4=y
-+# CONFIG_SMB_FS is not set
-+# CONFIG_NCP_FS is not set
-+# CONFIG_ZISOFS_FS is not set
-+CONFIG_ZLIB_FS_INFLATE=m
-+
-+#
-+# Partition Types
-+#
-+# CONFIG_PARTITION_ADVANCED is not set
-+CONFIG_MSDOS_PARTITION=y
-+# CONFIG_SMB_NLS is not set
-+CONFIG_NLS=y
-+
-+#
-+# Native Language Support
-+#
-+CONFIG_NLS_DEFAULT="iso8859-1"
-+# CONFIG_NLS_CODEPAGE_437 is not set
-+# CONFIG_NLS_CODEPAGE_737 is not set
-+# CONFIG_NLS_CODEPAGE_775 is not set
-+# CONFIG_NLS_CODEPAGE_850 is not set
-+# CONFIG_NLS_CODEPAGE_852 is not set
-+# CONFIG_NLS_CODEPAGE_855 is not set
-+# CONFIG_NLS_CODEPAGE_857 is not set
-+# CONFIG_NLS_CODEPAGE_860 is not set
-+# CONFIG_NLS_CODEPAGE_861 is not set
-+# CONFIG_NLS_CODEPAGE_862 is not set
-+# CONFIG_NLS_CODEPAGE_863 is not set
-+# CONFIG_NLS_CODEPAGE_864 is not set
-+# CONFIG_NLS_CODEPAGE_865 is not set
-+# CONFIG_NLS_CODEPAGE_866 is not set
-+# CONFIG_NLS_CODEPAGE_869 is not set
-+# CONFIG_NLS_CODEPAGE_936 is not set
-+# CONFIG_NLS_CODEPAGE_950 is not set
-+# CONFIG_NLS_CODEPAGE_932 is not set
-+# CONFIG_NLS_CODEPAGE_949 is not set
-+# CONFIG_NLS_CODEPAGE_874 is not set
-+# CONFIG_NLS_ISO8859_8 is not set
-+# CONFIG_NLS_CODEPAGE_1250 is not set
-+# CONFIG_NLS_CODEPAGE_1251 is not set
-+# CONFIG_NLS_ISO8859_1 is not set
-+# CONFIG_NLS_ISO8859_2 is not set
-+# CONFIG_NLS_ISO8859_3 is not set
-+# CONFIG_NLS_ISO8859_4 is not set
-+# CONFIG_NLS_ISO8859_5 is not set
-+# CONFIG_NLS_ISO8859_6 is not set
-+# CONFIG_NLS_ISO8859_7 is not set
-+# CONFIG_NLS_ISO8859_9 is not set
-+# CONFIG_NLS_ISO8859_13 is not set
-+# CONFIG_NLS_ISO8859_14 is not set
-+# CONFIG_NLS_ISO8859_15 is not set
-+# CONFIG_NLS_KOI8_R is not set
-+# CONFIG_NLS_KOI8_U is not set
-+# CONFIG_NLS_UTF8 is not set
-+
-+#
-+# SCSI support
-+#
-+CONFIG_SCSI=y
-+
-+#
-+# SCSI support type (disk, tape, CD-ROM)
-+#
-+# CONFIG_BLK_DEV_SD is not set
-+# CONFIG_CHR_DEV_ST is not set
-+# CONFIG_BLK_DEV_SR is not set
-+# CONFIG_CHR_DEV_SG is not set
-+
-+#
-+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-+#
-+# CONFIG_SCSI_DEBUG_QUEUES is not set
-+# CONFIG_SCSI_MULTI_LUN is not set
-+# CONFIG_SCSI_CONSTANTS is not set
-+# CONFIG_SCSI_LOGGING is not set
-+CONFIG_SCSI_DEBUG=m
-+
-+#
-+# Multi-device support (RAID and LVM)
-+#
-+# CONFIG_MD is not set
-+
-+#
-+# Memory Technology Devices (MTD)
-+#
-+# CONFIG_MTD is not set
-+
-+#
-+# Kernel hacking
-+#
-+# CONFIG_DEBUG_SLAB is not set
-+# CONFIG_DEBUGSYM is not set
-diff -Naur -X ../exclude-files orig/arch/um/config_scsi.in um/arch/um/config_scsi.in
---- orig/arch/um/config_scsi.in 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/config_scsi.in 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,30 @@
-+comment 'SCSI support type (disk, tape, CD-ROM)'
-+
-+dep_tristate ' SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI
-+
-+if [ "$CONFIG_BLK_DEV_SD" != "n" ]; then
-+ int 'Maximum number of SCSI disks that can be loaded as modules' CONFIG_SD_EXTRA_DEVS 40
-+fi
-+
-+dep_tristate ' SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
-+
-+dep_tristate ' SCSI CD-ROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
-+
-+if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then
-+ bool ' Enable vendor-specific extensions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR
-+ int 'Maximum number of CDROM devices that can be loaded as modules' CONFIG_SR_EXTRA_DEVS 2
-+fi
-+dep_tristate ' SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI
-+
-+comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs'
-+
-+#if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-+ bool ' Enable extra checks in new queueing code' CONFIG_SCSI_DEBUG_QUEUES
-+#fi
-+
-+bool ' Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN
-+
-+bool ' Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS
-+bool ' SCSI logging facility' CONFIG_SCSI_LOGGING
-+
-+dep_tristate 'SCSI debugging host simulator (EXPERIMENTAL)' CONFIG_SCSI_DEBUG $CONFIG_SCSI
-diff -Naur -X ../exclude-files orig/arch/um/defconfig um/arch/um/defconfig
---- orig/arch/um/defconfig 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/defconfig 2003-12-17 02:15:39.000000000 -0500
-@@ -0,0 +1,423 @@
-+#
-+# Automatically generated make config: don't edit
-+#
-+CONFIG_USERMODE=y
-+# CONFIG_ISA is not set
-+# CONFIG_SBUS is not set
-+# CONFIG_PCI is not set
-+CONFIG_UID16=y
-+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-+
-+#
-+# Code maturity level options
-+#
-+CONFIG_EXPERIMENTAL=y
-+
-+#
-+# General Setup
-+#
-+CONFIG_MODE_SKAS=y
-+CONFIG_MODE_TT=y
-+CONFIG_NET=y
-+CONFIG_SYSVIPC=y
-+CONFIG_BSD_PROCESS_ACCT=y
-+CONFIG_SYSCTL=y
-+CONFIG_BINFMT_AOUT=y
-+CONFIG_BINFMT_ELF=y
-+CONFIG_BINFMT_MISC=y
-+CONFIG_HOSTFS=y
-+CONFIG_HPPFS=y
-+CONFIG_MCONSOLE=y
-+CONFIG_MAGIC_SYSRQ=y
-+# CONFIG_HOST_2G_2G is not set
-+# CONFIG_UML_SMP is not set
-+# CONFIG_SMP is not set
-+CONFIG_NEST_LEVEL=0
-+CONFIG_KERNEL_HALF_GIGS=1
-+# CONFIG_HIGHMEM is not set
-+CONFIG_PROC_MM=y
-+CONFIG_KERNEL_STACK_ORDER=2
-+CONFIG_UML_REAL_TIME_CLOCK=y
-+
-+#
-+# Loadable module support
-+#
-+CONFIG_MODULES=y
-+# CONFIG_KMOD is not set
-+
-+#
-+# Character Devices
-+#
-+CONFIG_STDIO_CONSOLE=y
-+CONFIG_SSL=y
-+CONFIG_FD_CHAN=y
-+CONFIG_NULL_CHAN=y
-+CONFIG_PORT_CHAN=y
-+CONFIG_PTY_CHAN=y
-+CONFIG_TTY_CHAN=y
-+CONFIG_XTERM_CHAN=y
-+CONFIG_CON_ZERO_CHAN="fd:0,fd:1"
-+CONFIG_CON_CHAN="xterm"
-+CONFIG_SSL_CHAN="pty"
-+CONFIG_UNIX98_PTYS=y
-+CONFIG_UNIX98_PTY_COUNT=256
-+# CONFIG_WATCHDOG is not set
-+# CONFIG_WATCHDOG_NOWAYOUT is not set
-+# CONFIG_SOFT_WATCHDOG is not set
-+# CONFIG_UML_WATCHDOG is not set
-+CONFIG_UML_SOUND=y
-+CONFIG_SOUND=y
-+CONFIG_HOSTAUDIO=y
-+# CONFIG_TTY_LOG is not set
-+
-+#
-+# Block Devices
-+#
-+CONFIG_BLK_DEV_UBD=y
-+# CONFIG_BLK_DEV_UBD_SYNC is not set
-+# CONFIG_COW is not set
-+CONFIG_COW_COMMON=y
-+CONFIG_BLK_DEV_LOOP=y
-+CONFIG_BLK_DEV_NBD=y
-+CONFIG_BLK_DEV_RAM=y
-+CONFIG_BLK_DEV_RAM_SIZE=4096
-+CONFIG_BLK_DEV_INITRD=y
-+# CONFIG_MMAPPER is not set
-+CONFIG_NETDEVICES=y
-+
-+#
-+# Network Devices
-+#
-+CONFIG_UML_NET=y
-+CONFIG_UML_NET_ETHERTAP=y
-+CONFIG_UML_NET_TUNTAP=y
-+CONFIG_UML_NET_SLIP=y
-+CONFIG_UML_NET_SLIRP=y
-+CONFIG_UML_NET_DAEMON=y
-+CONFIG_UML_NET_MCAST=y
-+# CONFIG_UML_NET_PCAP is not set
-+CONFIG_DUMMY=y
-+# CONFIG_BONDING is not set
-+# CONFIG_EQUALIZER is not set
-+CONFIG_TUN=y
-+CONFIG_PPP=y
-+# CONFIG_PPP_MULTILINK is not set
-+# CONFIG_PPP_FILTER is not set
-+# CONFIG_PPP_ASYNC is not set
-+# CONFIG_PPP_SYNC_TTY is not set
-+# CONFIG_PPP_DEFLATE is not set
-+# CONFIG_PPP_BSDCOMP is not set
-+# CONFIG_PPPOE is not set
-+CONFIG_SLIP=y
-+# CONFIG_SLIP_COMPRESSED is not set
-+# CONFIG_SLIP_SMART is not set
-+# CONFIG_SLIP_MODE_SLIP6 is not set
-+
-+#
-+# Networking options
-+#
-+CONFIG_PACKET=y
-+CONFIG_PACKET_MMAP=y
-+# CONFIG_NETLINK_DEV is not set
-+# CONFIG_NETFILTER is not set
-+# CONFIG_FILTER is not set
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+# CONFIG_IP_MULTICAST is not set
-+# CONFIG_IP_ADVANCED_ROUTER is not set
-+# CONFIG_IP_PNP is not set
-+# CONFIG_NET_IPIP is not set
-+# CONFIG_NET_IPGRE is not set
-+# CONFIG_ARPD is not set
-+# CONFIG_INET_ECN is not set
-+# CONFIG_SYN_COOKIES is not set
-+# CONFIG_IPV6 is not set
-+# CONFIG_KHTTPD is not set
-+
-+#
-+# SCTP Configuration (EXPERIMENTAL)
-+#
-+CONFIG_IPV6_SCTP__=y
-+# CONFIG_IP_SCTP is not set
-+# CONFIG_ATM is not set
-+# CONFIG_VLAN_8021Q is not set
-+
-+#
-+#
-+#
-+# CONFIG_IPX is not set
-+# CONFIG_ATALK is not set
-+
-+#
-+# Appletalk devices
-+#
-+# CONFIG_DEV_APPLETALK is not set
-+# CONFIG_DECNET is not set
-+# CONFIG_BRIDGE is not set
-+# CONFIG_X25 is not set
-+# CONFIG_LAPB is not set
-+# CONFIG_LLC is not set
-+# CONFIG_NET_DIVERT is not set
-+# CONFIG_ECONET is not set
-+# CONFIG_WAN_ROUTER is not set
-+# CONFIG_NET_FASTROUTE is not set
-+# CONFIG_NET_HW_FLOWCONTROL is not set
-+
-+#
-+# QoS and/or fair queueing
-+#
-+# CONFIG_NET_SCHED is not set
-+
-+#
-+# Network testing
-+#
-+# CONFIG_NET_PKTGEN is not set
-+
-+#
-+# File systems
-+#
-+CONFIG_QUOTA=y
-+# CONFIG_QFMT_V2 is not set
-+CONFIG_AUTOFS_FS=y
-+CONFIG_AUTOFS4_FS=y
-+CONFIG_REISERFS_FS=y
-+# CONFIG_REISERFS_CHECK is not set
-+# CONFIG_REISERFS_PROC_INFO is not set
-+# CONFIG_ADFS_FS is not set
-+# CONFIG_ADFS_FS_RW is not set
-+# CONFIG_AFFS_FS is not set
-+# CONFIG_HFS_FS is not set
-+# CONFIG_HFSPLUS_FS is not set
-+# CONFIG_BEFS_FS is not set
-+# CONFIG_BEFS_DEBUG is not set
-+# CONFIG_BFS_FS is not set
-+# CONFIG_EXT3_FS is not set
-+# CONFIG_JBD is not set
-+# CONFIG_JBD_DEBUG is not set
-+CONFIG_FAT_FS=y
-+CONFIG_MSDOS_FS=y
-+CONFIG_UMSDOS_FS=y
-+CONFIG_VFAT_FS=y
-+# CONFIG_EFS_FS is not set
-+CONFIG_JFFS_FS=y
-+CONFIG_JFFS_FS_VERBOSE=0
-+CONFIG_JFFS_PROC_FS=y
-+CONFIG_JFFS2_FS=y
-+CONFIG_JFFS2_FS_DEBUG=0
-+# CONFIG_CRAMFS is not set
-+# CONFIG_TMPFS is not set
-+CONFIG_RAMFS=y
-+CONFIG_ISO9660_FS=y
-+# CONFIG_JOLIET is not set
-+# CONFIG_ZISOFS is not set
-+# CONFIG_JFS_FS is not set
-+# CONFIG_JFS_DEBUG is not set
-+# CONFIG_JFS_STATISTICS is not set
-+CONFIG_MINIX_FS=y
-+# CONFIG_VXFS_FS is not set
-+# CONFIG_NTFS_FS is not set
-+# CONFIG_NTFS_RW is not set
-+# CONFIG_HPFS_FS is not set
-+CONFIG_PROC_FS=y
-+CONFIG_DEVFS_FS=y
-+CONFIG_DEVFS_MOUNT=y
-+# CONFIG_DEVFS_DEBUG is not set
-+CONFIG_DEVPTS_FS=y
-+# CONFIG_QNX4FS_FS is not set
-+# CONFIG_QNX4FS_RW is not set
-+# CONFIG_ROMFS_FS is not set
-+CONFIG_EXT2_FS=y
-+# CONFIG_SYSV_FS is not set
-+# CONFIG_UDF_FS is not set
-+# CONFIG_UDF_RW is not set
-+# CONFIG_UFS_FS is not set
-+# CONFIG_UFS_FS_WRITE is not set
-+
-+#
-+# Network File Systems
-+#
-+# CONFIG_CODA_FS is not set
-+# CONFIG_INTERMEZZO_FS is not set
-+# CONFIG_NFS_FS is not set
-+# CONFIG_NFS_V3 is not set
-+# CONFIG_NFS_DIRECTIO is not set
-+# CONFIG_ROOT_NFS is not set
-+# CONFIG_NFSD is not set
-+# CONFIG_NFSD_V3 is not set
-+# CONFIG_NFSD_TCP is not set
-+# CONFIG_SUNRPC is not set
-+# CONFIG_LOCKD is not set
-+# CONFIG_SMB_FS is not set
-+# CONFIG_NCP_FS is not set
-+# CONFIG_NCPFS_PACKET_SIGNING is not set
-+# CONFIG_NCPFS_IOCTL_LOCKING is not set
-+# CONFIG_NCPFS_STRONG is not set
-+# CONFIG_NCPFS_NFS_NS is not set
-+# CONFIG_NCPFS_OS2_NS is not set
-+# CONFIG_NCPFS_SMALLDOS is not set
-+# CONFIG_NCPFS_NLS is not set
-+# CONFIG_NCPFS_EXTRAS is not set
-+# CONFIG_ZISOFS_FS is not set
-+
-+#
-+# Partition Types
-+#
-+# CONFIG_PARTITION_ADVANCED is not set
-+CONFIG_MSDOS_PARTITION=y
-+# CONFIG_SMB_NLS is not set
-+CONFIG_NLS=y
-+
-+#
-+# Native Language Support
-+#
-+CONFIG_NLS_DEFAULT="iso8859-1"
-+# CONFIG_NLS_CODEPAGE_437 is not set
-+# CONFIG_NLS_CODEPAGE_737 is not set
-+# CONFIG_NLS_CODEPAGE_775 is not set
-+# CONFIG_NLS_CODEPAGE_850 is not set
-+# CONFIG_NLS_CODEPAGE_852 is not set
-+# CONFIG_NLS_CODEPAGE_855 is not set
-+# CONFIG_NLS_CODEPAGE_857 is not set
-+# CONFIG_NLS_CODEPAGE_860 is not set
-+# CONFIG_NLS_CODEPAGE_861 is not set
-+# CONFIG_NLS_CODEPAGE_862 is not set
-+# CONFIG_NLS_CODEPAGE_863 is not set
-+# CONFIG_NLS_CODEPAGE_864 is not set
-+# CONFIG_NLS_CODEPAGE_865 is not set
-+# CONFIG_NLS_CODEPAGE_866 is not set
-+# CONFIG_NLS_CODEPAGE_869 is not set
-+# CONFIG_NLS_CODEPAGE_936 is not set
-+# CONFIG_NLS_CODEPAGE_950 is not set
-+# CONFIG_NLS_CODEPAGE_932 is not set
-+# CONFIG_NLS_CODEPAGE_949 is not set
-+# CONFIG_NLS_CODEPAGE_874 is not set
-+# CONFIG_NLS_ISO8859_8 is not set
-+# CONFIG_NLS_CODEPAGE_1250 is not set
-+# CONFIG_NLS_CODEPAGE_1251 is not set
-+# CONFIG_NLS_ISO8859_1 is not set
-+# CONFIG_NLS_ISO8859_2 is not set
-+# CONFIG_NLS_ISO8859_3 is not set
-+# CONFIG_NLS_ISO8859_4 is not set
-+# CONFIG_NLS_ISO8859_5 is not set
-+# CONFIG_NLS_ISO8859_6 is not set
-+# CONFIG_NLS_ISO8859_7 is not set
-+# CONFIG_NLS_ISO8859_9 is not set
-+# CONFIG_NLS_ISO8859_13 is not set
-+# CONFIG_NLS_ISO8859_14 is not set
-+# CONFIG_NLS_ISO8859_15 is not set
-+# CONFIG_NLS_KOI8_R is not set
-+# CONFIG_NLS_KOI8_U is not set
-+# CONFIG_NLS_UTF8 is not set
-+
-+#
-+# SCSI support
-+#
-+CONFIG_SCSI=y
-+
-+#
-+# SCSI support type (disk, tape, CD-ROM)
-+#
-+# CONFIG_BLK_DEV_SD is not set
-+# CONFIG_CHR_DEV_ST is not set
-+# CONFIG_BLK_DEV_SR is not set
-+# CONFIG_CHR_DEV_SG is not set
-+
-+#
-+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-+#
-+# CONFIG_SCSI_DEBUG_QUEUES is not set
-+# CONFIG_SCSI_MULTI_LUN is not set
-+# CONFIG_SCSI_CONSTANTS is not set
-+# CONFIG_SCSI_LOGGING is not set
-+CONFIG_SCSI_DEBUG=y
-+
-+#
-+# Multi-device support (RAID and LVM)
-+#
-+# CONFIG_MD is not set
-+# CONFIG_BLK_DEV_MD is not set
-+# CONFIG_MD_LINEAR is not set
-+# CONFIG_MD_RAID0 is not set
-+# CONFIG_MD_RAID1 is not set
-+# CONFIG_MD_RAID5 is not set
-+# CONFIG_MD_MULTIPATH is not set
-+# CONFIG_BLK_DEV_LVM is not set
-+
-+#
-+# Memory Technology Devices (MTD)
-+#
-+CONFIG_MTD=y
-+# CONFIG_MTD_DEBUG is not set
-+# CONFIG_MTD_PARTITIONS is not set
-+# CONFIG_MTD_CONCAT is not set
-+# CONFIG_MTD_REDBOOT_PARTS is not set
-+# CONFIG_MTD_CMDLINE_PARTS is not set
-+
-+#
-+# User Modules And Translation Layers
-+#
-+CONFIG_MTD_CHAR=y
-+CONFIG_MTD_BLOCK=y
-+# CONFIG_FTL is not set
-+# CONFIG_NFTL is not set
-+
-+#
-+# RAM/ROM/Flash chip drivers
-+#
-+# CONFIG_MTD_CFI is not set
-+# CONFIG_MTD_JEDECPROBE is not set
-+# CONFIG_MTD_GEN_PROBE is not set
-+# CONFIG_MTD_CFI_INTELEXT is not set
-+# CONFIG_MTD_CFI_AMDSTD is not set
-+# CONFIG_MTD_CFI_STAA is not set
-+# CONFIG_MTD_RAM is not set
-+# CONFIG_MTD_ROM is not set
-+# CONFIG_MTD_ABSENT is not set
-+# CONFIG_MTD_OBSOLETE_CHIPS is not set
-+# CONFIG_MTD_AMDSTD is not set
-+# CONFIG_MTD_SHARP is not set
-+# CONFIG_MTD_JEDEC is not set
-+
-+#
-+# Mapping drivers for chip access
-+#
-+# CONFIG_MTD_PHYSMAP is not set
-+# CONFIG_MTD_PCI is not set
-+# CONFIG_MTD_PCMCIA is not set
-+
-+#
-+# Self-contained MTD device drivers
-+#
-+# CONFIG_MTD_PMC551 is not set
-+# CONFIG_MTD_SLRAM is not set
-+# CONFIG_MTD_MTDRAM is not set
-+CONFIG_MTD_BLKMTD=y
-+
-+#
-+# Disk-On-Chip Device Drivers
-+#
-+# CONFIG_MTD_DOC1000 is not set
-+# CONFIG_MTD_DOC2000 is not set
-+# CONFIG_MTD_DOC2001 is not set
-+# CONFIG_MTD_DOCPROBE is not set
-+
-+#
-+# NAND Flash Device Drivers
-+#
-+# CONFIG_MTD_NAND is not set
-+
-+#
-+# Library routines
-+#
-+# CONFIG_CRC32 is not set
-+CONFIG_ZLIB_INFLATE=y
-+CONFIG_ZLIB_DEFLATE=y
-+
-+#
-+# Kernel hacking
-+#
-+# CONFIG_DEBUG_SLAB is not set
-+CONFIG_DEBUGSYM=y
-+CONFIG_PT_PROXY=y
-+# CONFIG_GPROF is not set
-+# CONFIG_GCOV is not set
-diff -Naur -X ../exclude-files orig/arch/um/drivers/chan_kern.c um/arch/um/drivers/chan_kern.c
---- orig/arch/um/drivers/chan_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/chan_kern.c 2003-11-07 07:25:34.000000000 -0500
-@@ -0,0 +1,519 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <linux/stddef.h>
-+#include <linux/kernel.h>
-+#include <linux/list.h>
-+#include <linux/slab.h>
-+#include <linux/tty.h>
-+#include <linux/string.h>
-+#include <linux/tty_flip.h>
-+#include <asm/irq.h>
-+#include "chan_kern.h"
-+#include "user_util.h"
-+#include "kern.h"
-+#include "irq_user.h"
-+#include "sigio.h"
-+#include "line.h"
-+
-+static void *not_configged_init(char *str, int device, struct chan_opts *opts)
-+{
-+ printk(KERN_ERR "Using a channel type which is configured out of "
-+ "UML\n");
-+ return(NULL);
-+}
-+
-+static int not_configged_open(int input, int output, int primary, void *data,
-+ char **dev_out)
-+{
-+ printk(KERN_ERR "Using a channel type which is configured out of "
-+ "UML\n");
-+ return(-ENODEV);
-+}
-+
-+static void not_configged_close(int fd, void *data)
-+{
-+ printk(KERN_ERR "Using a channel type which is configured out of "
-+ "UML\n");
-+}
-+
-+static int not_configged_read(int fd, char *c_out, void *data)
-+{
-+ printk(KERN_ERR "Using a channel type which is configured out of "
-+ "UML\n");
-+ return(-EIO);
-+}
-+
-+static int not_configged_write(int fd, const char *buf, int len, void *data)
-+{
-+ printk(KERN_ERR "Using a channel type which is configured out of "
-+ "UML\n");
-+ return(-EIO);
-+}
-+
-+static int not_configged_console_write(int fd, const char *buf, int len,
-+ void *data)
-+{
-+ printk(KERN_ERR "Using a channel type which is configured out of "
-+ "UML\n");
-+ return(-EIO);
-+}
-+
-+static int not_configged_window_size(int fd, void *data, unsigned short *rows,
-+ unsigned short *cols)
-+{
-+ printk(KERN_ERR "Using a channel type which is configured out of "
-+ "UML\n");
-+ return(-ENODEV);
-+}
-+
-+static void not_configged_free(void *data)
-+{
-+ printk(KERN_ERR "Using a channel type which is configured out of "
-+ "UML\n");
-+}
-+
-+static struct chan_ops not_configged_ops = {
-+ .init = not_configged_init,
-+ .open = not_configged_open,
-+ .close = not_configged_close,
-+ .read = not_configged_read,
-+ .write = not_configged_write,
-+ .console_write = not_configged_console_write,
-+ .window_size = not_configged_window_size,
-+ .free = not_configged_free,
-+ .winch = 0,
-+};
-+
-+static void tty_receive_char(struct tty_struct *tty, char ch)
-+{
-+ if(tty == NULL) return;
-+
-+ if(I_IXON(tty) && !I_IXOFF(tty) && !tty->raw) {
-+ if(ch == STOP_CHAR(tty)){
-+ stop_tty(tty);
-+ return;
-+ }
-+ else if(ch == START_CHAR(tty)){
-+ start_tty(tty);
-+ return;
-+ }
-+ }
-+
-+ if((tty->flip.flag_buf_ptr == NULL) ||
-+ (tty->flip.char_buf_ptr == NULL))
-+ return;
-+ tty_insert_flip_char(tty, ch, TTY_NORMAL);
-+}
-+
-+static int open_one_chan(struct chan *chan, int input, int output, int primary)
-+{
-+ int fd;
-+
-+ if(chan->opened) return(0);
-+ if(chan->ops->open == NULL) fd = 0;
-+ else fd = (*chan->ops->open)(input, output, primary, chan->data,
-+ &chan->dev);
-+ if(fd < 0) return(fd);
-+ chan->fd = fd;
-+
-+ chan->opened = 1;
-+ return(0);
-+}
-+
-+int open_chan(struct list_head *chans)
-+{
-+ struct list_head *ele;
-+ struct chan *chan;
-+ int ret, err = 0;
-+
-+ list_for_each(ele, chans){
-+ chan = list_entry(ele, struct chan, list);
-+ ret = open_one_chan(chan, chan->input, chan->output,
-+ chan->primary);
-+ if(chan->primary) err = ret;
-+ }
-+ return(err);
-+}
-+
-+void chan_enable_winch(struct list_head *chans, void *line)
-+{
-+ struct list_head *ele;
-+ struct chan *chan;
-+
-+ list_for_each(ele, chans){
-+ chan = list_entry(ele, struct chan, list);
-+ if(chan->primary && chan->output && chan->ops->winch){
-+ register_winch(chan->fd, line);
-+ return;
-+ }
-+ }
-+}
-+
-+void enable_chan(struct list_head *chans, void *data)
-+{
-+ struct list_head *ele;
-+ struct chan *chan;
-+
-+ list_for_each(ele, chans){
-+ chan = list_entry(ele, struct chan, list);
-+ if(!chan->opened) continue;
-+
-+ line_setup_irq(chan->fd, chan->input, chan->output, data);
-+ }
-+}
-+
-+void close_chan(struct list_head *chans)
-+{
-+ struct list_head *ele;
-+ struct chan *chan;
-+
-+ /* Close in reverse order as open in case more than one of them
-+ * refers to the same device and they save and restore that device's
-+ * state. Then, the first one opened will have the original state,
-+ * so it must be the last closed.
-+ */
-+ for(ele = chans->prev; ele != chans; ele = ele->prev){
-+ chan = list_entry(ele, struct chan, list);
-+ if(!chan->opened) continue;
-+ if(chan->ops->close != NULL)
-+ (*chan->ops->close)(chan->fd, chan->data);
-+ chan->opened = 0;
-+ chan->fd = -1;
-+ }
-+}
-+
-+int write_chan(struct list_head *chans, const char *buf, int len,
-+ int write_irq)
-+{
-+ struct list_head *ele;
-+ struct chan *chan;
-+ int n, ret = 0;
-+
-+ list_for_each(ele, chans){
-+ chan = list_entry(ele, struct chan, list);
-+ if(!chan->output || (chan->ops->write == NULL)) continue;
-+ n = chan->ops->write(chan->fd, buf, len, chan->data);
-+ if(chan->primary){
-+ ret = n;
-+ if((ret == -EAGAIN) || ((ret >= 0) && (ret < len))){
-+ reactivate_fd(chan->fd, write_irq);
-+ if(ret == -EAGAIN) ret = 0;
-+ }
-+ }
-+ }
-+ return(ret);
-+}
-+
-+int console_write_chan(struct list_head *chans, const char *buf, int len)
-+{
-+ struct list_head *ele;
-+ struct chan *chan;
-+ int n, ret = 0;
-+
-+ list_for_each(ele, chans){
-+ chan = list_entry(ele, struct chan, list);
-+ if(!chan->output || (chan->ops->console_write == NULL))
-+ continue;
-+ n = chan->ops->console_write(chan->fd, buf, len, chan->data);
-+ if(chan->primary) ret = n;
-+ }
-+ return(ret);
-+}
-+
-+int chan_window_size(struct list_head *chans, unsigned short *rows_out,
-+ unsigned short *cols_out)
-+{
-+ struct list_head *ele;
-+ struct chan *chan;
-+
-+ list_for_each(ele, chans){
-+ chan = list_entry(ele, struct chan, list);
-+ if(chan->primary){
-+ if(chan->ops->window_size == NULL) return(0);
-+ return(chan->ops->window_size(chan->fd, chan->data,
-+ rows_out, cols_out));
-+ }
-+ }
-+ return(0);
-+}
-+
-+void free_one_chan(struct chan *chan)
-+{
-+ list_del(&chan->list);
-+ if(chan->ops->free != NULL)
-+ (*chan->ops->free)(chan->data);
-+ free_irq_by_fd(chan->fd);
-+ if(chan->primary && chan->output) ignore_sigio_fd(chan->fd);
-+ kfree(chan);
-+}
-+
-+void free_chan(struct list_head *chans)
-+{
-+ struct list_head *ele, *next;
-+ struct chan *chan;
-+
-+ list_for_each_safe(ele, next, chans){
-+ chan = list_entry(ele, struct chan, list);
-+ free_one_chan(chan);
-+ }
-+}
-+
-+static int one_chan_config_string(struct chan *chan, char *str, int size,
-+ char **error_out)
-+{
-+ int n = 0;
-+
-+ if(chan == NULL){
-+ CONFIG_CHUNK(str, size, n, "none", 1);
-+ return(n);
-+ }
-+
-+ CONFIG_CHUNK(str, size, n, chan->ops->type, 0);
-+
-+ if(chan->dev == NULL){
-+ CONFIG_CHUNK(str, size, n, "", 1);
-+ return(n);
-+ }
-+
-+ CONFIG_CHUNK(str, size, n, ":", 0);
-+ CONFIG_CHUNK(str, size, n, chan->dev, 0);
-+
-+ return(n);
-+}
-+
-+static int chan_pair_config_string(struct chan *in, struct chan *out,
-+ char *str, int size, char **error_out)
-+{
-+ int n;
-+
-+ n = one_chan_config_string(in, str, size, error_out);
-+ str += n;
-+ size -= n;
-+
-+ if(in == out){
-+ CONFIG_CHUNK(str, size, n, "", 1);
-+ return(n);
-+ }
-+
-+ CONFIG_CHUNK(str, size, n, ",", 1);
-+ n = one_chan_config_string(out, str, size, error_out);
-+ str += n;
-+ size -= n;
-+ CONFIG_CHUNK(str, size, n, "", 1);
-+
-+ return(n);
-+}
-+
-+int chan_config_string(struct list_head *chans, char *str, int size,
-+ char **error_out)
-+{
-+ struct list_head *ele;
-+ struct chan *chan, *in = NULL, *out = NULL;
-+
-+ list_for_each(ele, chans){
-+ chan = list_entry(ele, struct chan, list);
-+ if(!chan->primary)
-+ continue;
-+ if(chan->input)
-+ in = chan;
-+ if(chan->output)
-+ out = chan;
-+ }
-+
-+ return(chan_pair_config_string(in, out, str, size, error_out));
-+}
-+
-+struct chan_type {
-+ char *key;
-+ struct chan_ops *ops;
-+};
-+
-+struct chan_type chan_table[] = {
-+#ifdef CONFIG_FD_CHAN
-+ { "fd", &fd_ops },
-+#else
-+ { "fd", ¬_configged_ops },
-+#endif
-+
-+#ifdef CONFIG_NULL_CHAN
-+ { "null", &null_ops },
-+#else
-+ { "null", ¬_configged_ops },
-+#endif
-+
-+#ifdef CONFIG_PORT_CHAN
-+ { "port", &port_ops },
-+#else
-+ { "port", ¬_configged_ops },
-+#endif
-+
-+#ifdef CONFIG_PTY_CHAN
-+ { "pty", &pty_ops },
-+ { "pts", &pts_ops },
-+#else
-+ { "pty", ¬_configged_ops },
-+ { "pts", ¬_configged_ops },
-+#endif
-+
-+#ifdef CONFIG_TTY_CHAN
-+ { "tty", &tty_ops },
-+#else
-+ { "tty", ¬_configged_ops },
-+#endif
-+
-+#ifdef CONFIG_XTERM_CHAN
-+ { "xterm", &xterm_ops },
-+#else
-+ { "xterm", ¬_configged_ops },
-+#endif
-+};
-+
-+static struct chan *parse_chan(char *str, int pri, int device,
-+ struct chan_opts *opts)
-+{
-+ struct chan_type *entry;
-+ struct chan_ops *ops;
-+ struct chan *chan;
-+ void *data;
-+ int i;
-+
-+ ops = NULL;
-+ data = NULL;
-+ for(i = 0; i < sizeof(chan_table)/sizeof(chan_table[0]); i++){
-+ entry = &chan_table[i];
-+ if(!strncmp(str, entry->key, strlen(entry->key))){
-+ ops = entry->ops;
-+ str += strlen(entry->key);
-+ break;
-+ }
-+ }
-+ if(ops == NULL){
-+ printk(KERN_ERR "parse_chan couldn't parse \"%s\"\n",
-+ str);
-+ return(NULL);
-+ }
-+ if(ops->init == NULL) return(NULL);
-+ data = (*ops->init)(str, device, opts);
-+ if(data == NULL) return(NULL);
-+
-+ chan = kmalloc(sizeof(*chan), GFP_KERNEL);
-+ if(chan == NULL) return(NULL);
-+ *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list),
-+ .primary = 1,
-+ .input = 0,
-+ .output = 0,
-+ .opened = 0,
-+ .fd = -1,
-+ .pri = pri,
-+ .ops = ops,
-+ .data = data });
-+ return(chan);
-+}
-+
-+int parse_chan_pair(char *str, struct list_head *chans, int pri, int device,
-+ struct chan_opts *opts)
-+{
-+ struct chan *new, *chan;
-+ char *in, *out;
-+
-+ if(!list_empty(chans)){
-+ chan = list_entry(chans->next, struct chan, list);
-+ if(chan->pri >= pri) return(0);
-+ free_chan(chans);
-+ INIT_LIST_HEAD(chans);
-+ }
-+
-+ out = strchr(str, ',');
-+ if(out != NULL){
-+ in = str;
-+ *out = '\0';
-+ out++;
-+ new = parse_chan(in, pri, device, opts);
-+ if(new == NULL) return(-1);
-+ new->input = 1;
-+ list_add(&new->list, chans);
-+
-+ new = parse_chan(out, pri, device, opts);
-+ if(new == NULL) return(-1);
-+ list_add(&new->list, chans);
-+ new->output = 1;
-+ }
-+ else {
-+ new = parse_chan(str, pri, device, opts);
-+ if(new == NULL) return(-1);
-+ list_add(&new->list, chans);
-+ new->input = 1;
-+ new->output = 1;
-+ }
-+ return(0);
-+}
-+
-+int chan_out_fd(struct list_head *chans)
-+{
-+ struct list_head *ele;
-+ struct chan *chan;
-+
-+ list_for_each(ele, chans){
-+ chan = list_entry(ele, struct chan, list);
-+ if(chan->primary && chan->output)
-+ return(chan->fd);
-+ }
-+ return(-1);
-+}
-+
-+void chan_interrupt(struct list_head *chans, struct tq_struct *task,
-+ struct tty_struct *tty, int irq, void *dev)
-+{
-+ struct list_head *ele, *next;
-+ struct chan *chan;
-+ int err;
-+ char c;
-+
-+ list_for_each_safe(ele, next, chans){
-+ chan = list_entry(ele, struct chan, list);
-+ if(!chan->input || (chan->ops->read == NULL)) continue;
-+ do {
-+ if((tty != NULL) &&
-+ (tty->flip.count >= TTY_FLIPBUF_SIZE)){
-+ queue_task(task, &tq_timer);
-+ goto out;
-+ }
-+ err = chan->ops->read(chan->fd, &c, chan->data);
-+ if(err > 0)
-+ tty_receive_char(tty, c);
-+ } while(err > 0);
-+
-+ if(err == 0) reactivate_fd(chan->fd, irq);
-+ if(err == -EIO){
-+ if(chan->primary){
-+ if(tty != NULL)
-+ tty_hangup(tty);
-+ line_disable(dev, irq);
-+ close_chan(chans);
-+ free_chan(chans);
-+ return;
-+ }
-+ else {
-+ if(chan->ops->close != NULL)
-+ chan->ops->close(chan->fd, chan->data);
-+ free_one_chan(chan);
-+ }
-+ }
-+ }
-+ out:
-+ if(tty) tty_flip_buffer_push(tty);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/chan_user.c um/arch/um/drivers/chan_user.c
---- orig/arch/um/drivers/chan_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/chan_user.c 2003-11-07 07:23:45.000000000 -0500
-@@ -0,0 +1,217 @@
-+/*
-+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <unistd.h>
-+#include <stdlib.h>
-+#include <errno.h>
-+#include <termios.h>
-+#include <string.h>
-+#include <signal.h>
-+#include <sys/stat.h>
-+#include <sys/ioctl.h>
-+#include <sys/socket.h>
-+#include "kern_util.h"
-+#include "user_util.h"
-+#include "chan_user.h"
-+#include "user.h"
-+#include "helper.h"
-+#include "os.h"
-+#include "choose-mode.h"
-+#include "mode.h"
-+
-+void generic_close(int fd, void *unused)
-+{
-+ os_close_file(fd);
-+}
-+
-+int generic_read(int fd, char *c_out, void *unused)
-+{
-+ int n;
-+
-+ n = os_read_file(fd, c_out, sizeof(*c_out));
-+
-+ if(n == -EAGAIN)
-+ return(0);
-+ else if(n == 0)
-+ return(-EIO);
-+ return(n);
-+}
-+
-+/* XXX Trivial wrapper around os_write_file */
-+
-+int generic_write(int fd, const char *buf, int n, void *unused)
-+{
-+ return(os_write_file(fd, buf, n));
-+}
-+
-+int generic_console_write(int fd, const char *buf, int n, void *unused)
-+{
-+ struct termios save, new;
-+ int err;
-+
-+ if(isatty(fd)){
-+ tcgetattr(fd, &save);
-+ new = save;
-+ new.c_oflag |= OPOST;
-+ tcsetattr(fd, TCSAFLUSH, &new);
-+ }
-+ err = generic_write(fd, buf, n, NULL);
-+ if(isatty(fd)) tcsetattr(fd, TCSAFLUSH, &save);
-+ return(err);
-+}
-+
-+int generic_window_size(int fd, void *unused, unsigned short *rows_out,
-+ unsigned short *cols_out)
-+{
-+ int rows, cols;
-+ int ret;
-+
-+ ret = os_window_size(fd, &rows, &cols);
-+ if(ret < 0)
-+ return(ret);
-+
-+ ret = ((*rows_out != rows) || (*cols_out != cols));
-+
-+ *rows_out = rows;
-+ *cols_out = cols;
-+
-+ return(ret);
-+}
-+
-+void generic_free(void *data)
-+{
-+ kfree(data);
-+}
-+
-+static void winch_handler(int sig)
-+{
-+}
-+
-+struct winch_data {
-+ int pty_fd;
-+ int pipe_fd;
-+ int close_me;
-+};
-+
-+static int winch_thread(void *arg)
-+{
-+ struct winch_data *data = arg;
-+ sigset_t sigs;
-+ int pty_fd, pipe_fd;
-+ int count, err;
-+ char c = 1;
-+
-+ os_close_file(data->close_me);
-+ pty_fd = data->pty_fd;
-+ pipe_fd = data->pipe_fd;
-+ count = os_write_file(pipe_fd, &c, sizeof(c));
-+ if(count != sizeof(c))
-+ printk("winch_thread : failed to write synchronization "
-+ "byte, err = %d\n", -count);
-+
-+ signal(SIGWINCH, winch_handler);
-+ sigfillset(&sigs);
-+ sigdelset(&sigs, SIGWINCH);
-+ if(sigprocmask(SIG_SETMASK, &sigs, NULL) < 0){
-+ printk("winch_thread : sigprocmask failed, errno = %d\n",
-+ errno);
-+ exit(1);
-+ }
-+
-+ if(setsid() < 0){
-+ printk("winch_thread : setsid failed, errno = %d\n", errno);
-+ exit(1);
-+ }
-+
-+ err = os_new_tty_pgrp(pty_fd, os_getpid());
-+ if(err < 0){
-+ printk("winch_thread : new_tty_pgrp failed, err = %d\n", -err);
-+ exit(1);
-+ }
-+
-+ count = os_read_file(pipe_fd, &c, sizeof(c));
-+ if(count != sizeof(c))
-+ printk("winch_thread : failed to read synchronization byte, "
-+ "err = %d\n", -count);
-+
-+ while(1){
-+ pause();
-+
-+ count = os_write_file(pipe_fd, &c, sizeof(c));
-+ if(count != sizeof(c))
-+ printk("winch_thread : write failed, err = %d\n",
-+ -count);
-+ }
-+}
-+
-+static int winch_tramp(int fd, void *device_data, int *fd_out)
-+{
-+ struct winch_data data;
-+ unsigned long stack;
-+ int fds[2], pid, n, err;
-+ char c;
-+
-+ err = os_pipe(fds, 1, 1);
-+ if(err < 0){
-+ printk("winch_tramp : os_pipe failed, err = %d\n", -err);
-+ return(err);
-+ }
-+
-+ data = ((struct winch_data) { .pty_fd = fd,
-+ .pipe_fd = fds[1],
-+ .close_me = fds[0] } );
-+ pid = run_helper_thread(winch_thread, &data, 0, &stack, 0);
-+ if(pid < 0){
-+ printk("fork of winch_thread failed - errno = %d\n", errno);
-+ return(pid);
-+ }
-+
-+ os_close_file(fds[1]);
-+ *fd_out = fds[0];
-+ n = os_read_file(fds[0], &c, sizeof(c));
-+ if(n != sizeof(c)){
-+ printk("winch_tramp : failed to read synchronization byte\n");
-+ printk("read failed, err = %d\n", -n);
-+ printk("fd %d will not support SIGWINCH\n", fd);
-+ *fd_out = -1;
-+ }
-+ return(pid);
-+}
-+
-+void register_winch(int fd, void *device_data)
-+{
-+ int pid, thread, thread_fd;
-+ int count;
-+ char c = 1;
-+
-+ if(!isatty(fd))
-+ return;
-+
-+ pid = tcgetpgrp(fd);
-+ if(!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd,
-+ device_data) && (pid == -1)){
-+ thread = winch_tramp(fd, device_data, &thread_fd);
-+ if(fd != -1){
-+ register_winch_irq(thread_fd, fd, thread, device_data);
-+
-+ count = os_write_file(thread_fd, &c, sizeof(c));
-+ if(count != sizeof(c))
-+ printk("register_winch : failed to write "
-+ "synchronization byte, err = %d\n",
-+ -count);
-+ }
-+ }
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/cow.h um/arch/um/drivers/cow.h
---- orig/arch/um/drivers/cow.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/cow.h 2004-01-16 03:45:20.000000000 -0500
-@@ -0,0 +1,41 @@
-+#ifndef __COW_H__
-+#define __COW_H__
-+
-+#include <asm/types.h>
-+
-+#if __BYTE_ORDER == __BIG_ENDIAN
-+# define ntohll(x) (x)
-+# define htonll(x) (x)
-+#elif __BYTE_ORDER == __LITTLE_ENDIAN
-+# define ntohll(x) bswap_64(x)
-+# define htonll(x) bswap_64(x)
-+#else
-+#error "__BYTE_ORDER not defined"
-+#endif
-+
-+extern int init_cow_file(int fd, char *cow_file, char *backing_file,
-+ int sectorsize, int alignment, int *bitmap_offset_out,
-+ unsigned long *bitmap_len_out, int *data_offset_out);
-+
-+extern int file_reader(__u64 offset, char *buf, int len, void *arg);
-+extern int read_cow_header(int (*reader)(__u64, char *, int, void *),
-+ void *arg, __u32 *version_out,
-+ char **backing_file_out, time_t *mtime_out,
-+ __u64 *size_out, int *sectorsize_out,
-+ __u32 *align_out, int *bitmap_offset_out);
-+
-+extern int write_cow_header(char *cow_file, int fd, char *backing_file,
-+ int sectorsize, int alignment, long long *size);
-+
-+extern void cow_sizes(int version, __u64 size, int sectorsize, int align,
-+ int bitmap_offset, unsigned long *bitmap_len_out,
-+ int *data_offset_out);
-+
-+#endif
-+
-+/*
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/cow_kern.c um/arch/um/drivers/cow_kern.c
---- orig/arch/um/drivers/cow_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/cow_kern.c 2004-01-10 05:55:04.000000000 -0500
-@@ -0,0 +1,630 @@
-+#define COW_MAJOR 60
-+#define MAJOR_NR COW_MAJOR
-+
-+#include <linux/stddef.h>
-+#include <linux/kernel.h>
-+#include <linux/ctype.h>
-+#include <linux/stat.h>
-+#include <linux/vmalloc.h>
-+#include <linux/blkdev.h>
-+#include <linux/blk.h>
-+#include <linux/fs.h>
-+#include <linux/genhd.h>
-+#include <linux/devfs_fs.h>
-+#include <asm/uaccess.h>
-+#include "2_5compat.h"
-+#include "cow.h"
-+#include "ubd_user.h"
-+
-+#define COW_SHIFT 4
-+
-+struct cow {
-+ int count;
-+ char *cow_path;
-+ dev_t cow_dev;
-+ struct block_device *cow_bdev;
-+ char *backing_path;
-+ dev_t backing_dev;
-+ struct block_device *backing_bdev;
-+ int sectorsize;
-+ unsigned long *bitmap;
-+ unsigned long bitmap_len;
-+ int bitmap_offset;
-+ int data_offset;
-+ devfs_handle_t devfs;
-+ struct semaphore sem;
-+ struct semaphore io_sem;
-+ atomic_t working;
-+ spinlock_t io_lock;
-+ struct buffer_head *bh;
-+ struct buffer_head *bhtail;
-+ void *end_io;
-+};
-+
-+#define DEFAULT_COW { \
-+ .count = 0, \
-+ .cow_path = NULL, \
-+ .cow_dev = 0, \
-+ .backing_path = NULL, \
-+ .backing_dev = 0, \
-+ .bitmap = NULL, \
-+ .bitmap_len = 0, \
-+ .bitmap_offset = 0, \
-+ .data_offset = 0, \
-+ .devfs = NULL, \
-+ .working = ATOMIC_INIT(0), \
-+ .io_lock = SPIN_LOCK_UNLOCKED, \
-+}
-+
-+#define MAX_DEV (8)
-+#define MAX_MINOR (MAX_DEV << COW_SHIFT)
-+
-+struct cow cow_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_COW };
-+
-+/* Not modified by this driver */
-+static int blk_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = BLOCK_SIZE };
-+static int hardsect_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 512 };
-+
-+/* Protected by cow_lock */
-+static int sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 0 };
-+
-+static struct hd_struct cow_part[MAX_MINOR] =
-+ { [ 0 ... MAX_MINOR - 1 ] = { 0, 0, 0 } };
-+
-+/* Protected by io_request_lock */
-+static request_queue_t *cow_queue;
-+
-+static int cow_open(struct inode *inode, struct file *filp);
-+static int cow_release(struct inode * inode, struct file * file);
-+static int cow_ioctl(struct inode * inode, struct file * file,
-+ unsigned int cmd, unsigned long arg);
-+static int cow_revalidate(kdev_t rdev);
-+
-+static struct block_device_operations cow_blops = {
-+ .open = cow_open,
-+ .release = cow_release,
-+ .ioctl = cow_ioctl,
-+ .revalidate = cow_revalidate,
-+};
-+
-+/* Initialized in an initcall, and unchanged thereafter */
-+devfs_handle_t cow_dir_handle;
-+
-+#define INIT_GENDISK(maj, name, parts, shift, bsizes, max, blops) \
-+{ \
-+ .major = maj, \
-+ .major_name = name, \
-+ .minor_shift = shift, \
-+ .max_p = 1 << shift, \
-+ .part = parts, \
-+ .sizes = bsizes, \
-+ .nr_real = max, \
-+ .real_devices = NULL, \
-+ .next = NULL, \
-+ .fops = blops, \
-+ .de_arr = NULL, \
-+ .flags = 0 \
-+}
-+
-+static spinlock_t cow_lock = SPIN_LOCK_UNLOCKED;
-+
-+static struct gendisk cow_gendisk = INIT_GENDISK(MAJOR_NR, "cow", cow_part,
-+ COW_SHIFT, sizes, MAX_DEV,
-+ &cow_blops);
-+
-+static int cow_add(int n)
-+{
-+ struct cow *dev = &cow_dev[n];
-+ char name[sizeof("nnnnnn\0")];
-+ int err = -ENODEV;
-+
-+ if(dev->cow_path == NULL)
-+ goto out;
-+
-+ sprintf(name, "%d", n);
-+ dev->devfs = devfs_register(cow_dir_handle, name, DEVFS_FL_REMOVABLE,
-+ MAJOR_NR, n << COW_SHIFT, S_IFBLK |
-+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
-+ &cow_blops, NULL);
-+
-+ init_MUTEX_LOCKED(&dev->sem);
-+ init_MUTEX(&dev->io_sem);
-+
-+ return(0);
-+
-+ out:
-+ return(err);
-+}
-+
-+/*
-+ * Add buffer_head to back of pending list
-+ */
-+static void cow_add_bh(struct cow *cow, struct buffer_head *bh)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&cow->io_lock, flags);
-+ if(cow->bhtail != NULL){
-+ cow->bhtail->b_reqnext = bh;
-+ cow->bhtail = bh;
-+ }
-+ else {
-+ cow->bh = bh;
-+ cow->bhtail = bh;
-+ }
-+ spin_unlock_irqrestore(&cow->io_lock, flags);
-+}
-+
-+/*
-+ * Grab first pending buffer
-+ */
-+static struct buffer_head *cow_get_bh(struct cow *cow)
-+{
-+ struct buffer_head *bh;
-+
-+ spin_lock_irq(&cow->io_lock);
-+ bh = cow->bh;
-+ if(bh != NULL){
-+ if(bh == cow->bhtail)
-+ cow->bhtail = NULL;
-+ cow->bh = bh->b_reqnext;
-+ bh->b_reqnext = NULL;
-+ }
-+ spin_unlock_irq(&cow->io_lock);
-+
-+ return(bh);
-+}
-+
-+static void cow_handle_bh(struct cow *cow, struct buffer_head *bh,
-+ struct buffer_head **cow_bh, int ncow_bh)
-+{
-+ int i;
-+
-+ if(ncow_bh > 0)
-+ ll_rw_block(WRITE, ncow_bh, cow_bh);
-+
-+ for(i = 0; i < ncow_bh ; i++){
-+ wait_on_buffer(cow_bh[i]);
-+ brelse(cow_bh[i]);
-+ }
-+
-+ ll_rw_block(WRITE, 1, &bh);
-+ brelse(bh);
-+}
-+
-+static struct buffer_head *cow_new_bh(struct cow *dev, int sector)
-+{
-+ struct buffer_head *bh;
-+
-+ sector = (dev->bitmap_offset + sector / 8) / dev->sectorsize;
-+ bh = getblk(dev->cow_dev, sector, dev->sectorsize);
-+ memcpy(bh->b_data, dev->bitmap + sector / (8 * sizeof(dev->bitmap[0])),
-+ dev->sectorsize);
-+ return(bh);
-+}
-+
-+/* Copied from loop.c, needed to avoid deadlocking in make_request. */
-+
-+static int cow_thread(void *data)
-+{
-+ struct cow *dev = data;
-+ struct buffer_head *bh;
-+
-+ daemonize();
-+ exit_files(current);
-+
-+ sprintf(current->comm, "cow%d", dev - cow_dev);
-+
-+ spin_lock_irq(¤t->sigmask_lock);
-+ sigfillset(¤t->blocked);
-+ flush_signals(current);
-+ spin_unlock_irq(¤t->sigmask_lock);
-+
-+ atomic_inc(&dev->working);
-+
-+ current->policy = SCHED_OTHER;
-+ current->nice = -20;
-+
-+ current->flags |= PF_NOIO;
-+
-+ /*
-+ * up sem, we are running
-+ */
-+ up(&dev->sem);
-+
-+ for(;;){
-+ int start, len, nbh, i, update_bitmap = 0;
-+ struct buffer_head *cow_bh[2];
-+
-+ down_interruptible(&dev->io_sem);
-+ /*
-+ * could be upped because of tear-down, not because of
-+ * pending work
-+ */
-+ if(!atomic_read(&dev->working))
-+ break;
-+
-+ bh = cow_get_bh(dev);
-+ if(bh == NULL){
-+ printk(KERN_ERR "cow: missing bh\n");
-+ continue;
-+ }
-+
-+ start = bh->b_blocknr * bh->b_size / dev->sectorsize;
-+ len = bh->b_size / dev->sectorsize;
-+ for(i = 0; i < len ; i++){
-+ if(ubd_test_bit(start + i,
-+ (unsigned char *) dev->bitmap))
-+ continue;
-+
-+ update_bitmap = 1;
-+ ubd_set_bit(start + i, (unsigned char *) dev->bitmap);
-+ }
-+
-+ cow_bh[0] = NULL;
-+ cow_bh[1] = NULL;
-+ nbh = 0;
-+ if(update_bitmap){
-+ cow_bh[0] = cow_new_bh(dev, start);
-+ nbh++;
-+ if(start / dev->sectorsize !=
-+ (start + len) / dev->sectorsize){
-+ cow_bh[1] = cow_new_bh(dev, start + len);
-+ nbh++;
-+ }
-+ }
-+
-+ bh->b_dev = dev->cow_dev;
-+ bh->b_blocknr += dev->data_offset / dev->sectorsize;
-+
-+ cow_handle_bh(dev, bh, cow_bh, nbh);
-+
-+ /*
-+ * upped both for pending work and tear-down, lo_pending
-+ * will hit zero then
-+ */
-+ if(atomic_dec_and_test(&dev->working))
-+ break;
-+ }
-+
-+ up(&dev->sem);
-+ return(0);
-+}
-+
-+static int cow_make_request(request_queue_t *q, int rw, struct buffer_head *bh)
-+{
-+ struct cow *dev;
-+ int n, minor;
-+
-+ minor = MINOR(bh->b_rdev);
-+ n = minor >> COW_SHIFT;
-+ dev = &cow_dev[n];
-+
-+ dev->end_io = NULL;
-+ if(ubd_test_bit(bh->b_rsector, (unsigned char *) dev->bitmap)){
-+ bh->b_rdev = dev->cow_dev;
-+ bh->b_rsector += dev->data_offset / dev->sectorsize;
-+ }
-+ else if(rw == WRITE){
-+ bh->b_dev = dev->cow_dev;
-+ bh->b_blocknr += dev->data_offset / dev->sectorsize;
-+
-+ cow_add_bh(dev, bh);
-+ up(&dev->io_sem);
-+ return(0);
-+ }
-+ else {
-+ bh->b_rdev = dev->backing_dev;
-+ }
-+
-+ return(1);
-+}
-+
-+int cow_init(void)
-+{
-+ int i;
-+
-+ cow_dir_handle = devfs_mk_dir (NULL, "cow", NULL);
-+ if (devfs_register_blkdev(MAJOR_NR, "cow", &cow_blops)) {
-+ printk(KERN_ERR "cow: unable to get major %d\n", MAJOR_NR);
-+ return -1;
-+ }
-+ read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */
-+ blksize_size[MAJOR_NR] = blk_sizes;
-+ blk_size[MAJOR_NR] = sizes;
-+ INIT_HARDSECT(hardsect_size, MAJOR_NR, hardsect_sizes);
-+
-+ cow_queue = BLK_DEFAULT_QUEUE(MAJOR_NR);
-+ blk_init_queue(cow_queue, NULL);
-+ INIT_ELV(cow_queue, &cow_queue->elevator);
-+ blk_queue_make_request(cow_queue, cow_make_request);
-+
-+ add_gendisk(&cow_gendisk);
-+
-+ for(i=0;i<MAX_DEV;i++)
-+ cow_add(i);
-+
-+ return(0);
-+}
-+
-+__initcall(cow_init);
-+
-+static int reader(__u64 start, char *buf, int count, void *arg)
-+{
-+ dev_t dev = *((dev_t *) arg);
-+ struct buffer_head *bh;
-+ __u64 block;
-+ int cur, offset, left, n, blocksize = get_hardsect_size(dev);
-+
-+ if(blocksize == 0)
-+ panic("Zero blocksize");
-+
-+ block = start / blocksize;
-+ offset = start % blocksize;
-+ left = count;
-+ cur = 0;
-+ while(left > 0){
-+ n = (left > blocksize) ? blocksize : left;
-+
-+ bh = bread(dev, block, (n < 512) ? 512 : n);
-+ if(bh == NULL)
-+ return(-EIO);
-+
-+ n -= offset;
-+ memcpy(&buf[cur], bh->b_data + offset, n);
-+ block++;
-+ left -= n;
-+ cur += n;
-+ offset = 0;
-+ brelse(bh);
-+ }
-+
-+ return(count);
-+}
-+
-+static int cow_open(struct inode *inode, struct file *filp)
-+{
-+ int (*dev_ioctl)(struct inode *, struct file *, unsigned int,
-+ unsigned long);
-+ mm_segment_t fs;
-+ struct cow *dev;
-+ __u64 size;
-+ __u32 version, align;
-+ time_t mtime;
-+ char *backing_file;
-+ int n, offset, err = 0;
-+
-+ n = DEVICE_NR(inode->i_rdev);
-+ if(n >= MAX_DEV)
-+ return(-ENODEV);
-+ dev = &cow_dev[n];
-+ offset = n << COW_SHIFT;
-+
-+ spin_lock(&cow_lock);
-+
-+ if(dev->count == 0){
-+ dev->cow_dev = name_to_kdev_t(dev->cow_path);
-+ if(dev->cow_dev == 0){
-+ printk(KERN_ERR "cow_open - name_to_kdev_t(\"%s\") "
-+ "failed\n", dev->cow_path);
-+ err = -ENODEV;
-+ }
-+
-+ dev->backing_dev = name_to_kdev_t(dev->backing_path);
-+ if(dev->backing_dev == 0){
-+ printk(KERN_ERR "cow_open - name_to_kdev_t(\"%s\") "
-+ "failed\n", dev->backing_path);
-+ err = -ENODEV;
-+ }
-+
-+ if(err)
-+ goto out;
-+
-+ dev->cow_bdev = bdget(dev->cow_dev);
-+ if(dev->cow_bdev == NULL){
-+ printk(KERN_ERR "cow_open - bdget(\"%s\") failed\n",
-+ dev->cow_path);
-+ err = -ENOMEM;
-+ }
-+ dev->backing_bdev = bdget(dev->backing_dev);
-+ if(dev->backing_bdev == NULL){
-+ printk(KERN_ERR "cow_open - bdget(\"%s\") failed\n",
-+ dev->backing_path);
-+ err = -ENOMEM;
-+ }
-+
-+ if(err)
-+ goto out;
-+
-+ err = blkdev_get(dev->cow_bdev, FMODE_READ|FMODE_WRITE, 0,
-+ BDEV_RAW);
-+ if(err){
-+ printk("cow_open - blkdev_get of COW device failed, "
-+ "error = %d\n", err);
-+ goto out;
-+ }
-+
-+ err = blkdev_get(dev->backing_bdev, FMODE_READ, 0, BDEV_RAW);
-+ if(err){
-+ printk("cow_open - blkdev_get of backing device "
-+ "failed, error = %d\n", err);
-+ goto out;
-+ }
-+
-+ err = read_cow_header(reader, &dev->cow_dev, &version,
-+ &backing_file, &mtime, &size,
-+ &dev->sectorsize, &align,
-+ &dev->bitmap_offset);
-+ if(err){
-+ printk(KERN_ERR "cow_open - read_cow_header failed, "
-+ "err = %d\n", err);
-+ goto out;
-+ }
-+
-+ cow_sizes(version, size, dev->sectorsize, align,
-+ dev->bitmap_offset, &dev->bitmap_len,
-+ &dev->data_offset);
-+ dev->bitmap = (void *) vmalloc(dev->bitmap_len);
-+ if(dev->bitmap == NULL){
-+ err = -ENOMEM;
-+ printk(KERN_ERR "Failed to vmalloc COW bitmap\n");
-+ goto out;
-+ }
-+ flush_tlb_kernel_vm();
-+
-+ err = reader(dev->bitmap_offset, (char *) dev->bitmap,
-+ dev->bitmap_len, &dev->cow_dev);
-+ if(err < 0){
-+ printk(KERN_ERR "Failed to read COW bitmap\n");
-+ vfree(dev->bitmap);
-+ goto out;
-+ }
-+
-+ dev_ioctl = dev->backing_bdev->bd_op->ioctl;
-+ fs = get_fs();
-+ set_fs(KERNEL_DS);
-+ err = (*dev_ioctl)(inode, filp, BLKGETSIZE,
-+ (unsigned long) &sizes[offset]);
-+ set_fs(fs);
-+ if(err){
-+ printk(KERN_ERR "cow_open - BLKGETSIZE failed, "
-+ "error = %d\n", err);
-+ goto out;
-+ }
-+
-+ kernel_thread(cow_thread, dev,
-+ CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
-+ down(&dev->sem);
-+ }
-+ dev->count++;
-+ out:
-+ spin_unlock(&cow_lock);
-+ return(err);
-+}
-+
-+static int cow_release(struct inode * inode, struct file * file)
-+{
-+ struct cow *dev;
-+ int n, err;
-+
-+ n = DEVICE_NR(inode->i_rdev);
-+ if(n >= MAX_DEV)
-+ return(-ENODEV);
-+ dev = &cow_dev[n];
-+
-+ spin_lock(&cow_lock);
-+
-+ if(--dev->count > 0)
-+ goto out;
-+
-+ err = blkdev_put(dev->cow_bdev, BDEV_RAW);
-+ if(err)
-+ printk("cow_release - blkdev_put of cow device failed, "
-+ "error = %d\n", err);
-+ bdput(dev->cow_bdev);
-+ dev->cow_bdev = 0;
-+
-+ err = blkdev_put(dev->backing_bdev, BDEV_RAW);
-+ if(err)
-+ printk("cow_release - blkdev_put of backing device failed, "
-+ "error = %d\n", err);
-+ bdput(dev->backing_bdev);
-+ dev->backing_bdev = 0;
-+
-+ out:
-+ spin_unlock(&cow_lock);
-+ return(0);
-+}
-+
-+static int cow_ioctl(struct inode * inode, struct file * file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ struct cow *dev;
-+ int (*dev_ioctl)(struct inode *, struct file *, unsigned int,
-+ unsigned long);
-+ int n;
-+
-+ n = DEVICE_NR(inode->i_rdev);
-+ if(n >= MAX_DEV)
-+ return(-ENODEV);
-+ dev = &cow_dev[n];
-+
-+ dev_ioctl = dev->backing_bdev->bd_op->ioctl;
-+ return((*dev_ioctl)(inode, file, cmd, arg));
-+}
-+
-+static int cow_revalidate(kdev_t rdev)
-+{
-+ printk(KERN_ERR "Need to implement cow_revalidate\n");
-+ return(0);
-+}
-+
-+static int parse_unit(char **ptr)
-+{
-+ char *str = *ptr, *end;
-+ int n = -1;
-+
-+ if(isdigit(*str)) {
-+ n = simple_strtoul(str, &end, 0);
-+ if(end == str)
-+ return(-1);
-+ *ptr = end;
-+ }
-+ else if (('a' <= *str) && (*str <= 'h')) {
-+ n = *str - 'a';
-+ str++;
-+ *ptr = str;
-+ }
-+ return(n);
-+}
-+
-+static int cow_setup(char *str)
-+{
-+ struct cow *dev;
-+ char *cow_name, *backing_name;
-+ int unit;
-+
-+ unit = parse_unit(&str);
-+ if(unit < 0){
-+ printk(KERN_ERR "cow_setup - Couldn't parse unit number\n");
-+ return(1);
-+ }
-+
-+ if(*str != '='){
-+ printk(KERN_ERR "cow_setup - Missing '=' after unit "
-+ "number\n");
-+ return(1);
-+ }
-+ str++;
-+
-+ cow_name = str;
-+ backing_name = strchr(str, ',');
-+ if(backing_name == NULL){
-+ printk(KERN_ERR "cow_setup - missing backing device name\n");
-+ return(0);
-+ }
-+ *backing_name = '\0';
-+ backing_name++;
-+
-+ spin_lock(&cow_lock);
-+
-+ dev = &cow_dev[unit];
-+ dev->cow_path = cow_name;
-+ dev->backing_path = backing_name;
-+
-+ spin_unlock(&cow_lock);
-+ return(0);
-+}
-+
-+__setup("cow", cow_setup);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/cow_sys.h um/arch/um/drivers/cow_sys.h
---- orig/arch/um/drivers/cow_sys.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/cow_sys.h 2003-12-17 10:53:03.000000000 -0500
-@@ -0,0 +1,48 @@
-+#ifndef __COW_SYS_H__
-+#define __COW_SYS_H__
-+
-+#include "kern_util.h"
-+#include "user_util.h"
-+#include "os.h"
-+#include "user.h"
-+
-+static inline void *cow_malloc(int size)
-+{
-+ return(um_kmalloc(size));
-+}
-+
-+static inline void cow_free(void *ptr)
-+{
-+ kfree(ptr);
-+}
-+
-+#define cow_printf printk
-+
-+static inline char *cow_strdup(char *str)
-+{
-+ return(uml_strdup(str));
-+}
-+
-+static inline int cow_seek_file(int fd, __u64 offset)
-+{
-+ return(os_seek_file(fd, offset));
-+}
-+
-+static inline int cow_file_size(char *file, __u64 *size_out)
-+{
-+ return(os_file_size(file, size_out));
-+}
-+
-+static inline int cow_write_file(int fd, char *buf, int size)
-+{
-+ return(os_write_file(fd, buf, size));
-+}
-+
-+#endif
-+
-+/*
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/cow_user.c um/arch/um/drivers/cow_user.c
---- orig/arch/um/drivers/cow_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/cow_user.c 2004-01-10 05:56:22.000000000 -0500
-@@ -0,0 +1,375 @@
-+#include <stddef.h>
-+#include <string.h>
-+#include <errno.h>
-+#include <unistd.h>
-+#include <byteswap.h>
-+#include <sys/time.h>
-+#include <sys/param.h>
-+#include <sys/user.h>
-+#include <netinet/in.h>
-+
-+#include "os.h"
-+
-+#include "cow.h"
-+#include "cow_sys.h"
-+
-+#define PATH_LEN_V1 256
-+
-+struct cow_header_v1 {
-+ int magic;
-+ int version;
-+ char backing_file[PATH_LEN_V1];
-+ time_t mtime;
-+ __u64 size;
-+ int sectorsize;
-+};
-+
-+#define PATH_LEN_V2 MAXPATHLEN
-+
-+struct cow_header_v2 {
-+ unsigned long magic;
-+ unsigned long version;
-+ char backing_file[PATH_LEN_V2];
-+ time_t mtime;
-+ __u64 size;
-+ int sectorsize;
-+};
-+
-+/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in
-+ * case other systems have different values for MAXPATHLEN
-+ */
-+#define PATH_LEN_V3 4096
-+
-+/* Changes from V2 -
-+ * PATH_LEN_V3 as described above
-+ * Explicitly specify field bit lengths for systems with different
-+ * lengths for the usual C types. Not sure whether char or
-+ * time_t should be changed, this can be changed later without
-+ * breaking compatibility
-+ * Add alignment field so that different alignments can be used for the
-+ * bitmap and data
-+ * Add cow_format field to allow for the possibility of different ways
-+ * of specifying the COW blocks. For now, the only value is 0,
-+ * for the traditional COW bitmap.
-+ * Move the backing_file field to the end of the header. This allows
-+ * for the possibility of expanding it into the padding required
-+ * by the bitmap alignment.
-+ * The bitmap and data portions of the file will be aligned as specified
-+ * by the alignment field. This is to allow COW files to be
-+ * put on devices with restrictions on access alignments, such as
-+ * /dev/raw, with a 512 byte alignment restriction. This also
-+ * allows the data to be more aligned more strictly than on
-+ * sector boundaries. This is needed for ubd-mmap, which needs
-+ * the data to be page aligned.
-+ * Fixed (finally!) the rounding bug
-+ */
-+
-+struct cow_header_v3 {
-+ __u32 magic;
-+ __u32 version;
-+ time_t mtime;
-+ __u64 size;
-+ __u32 sectorsize;
-+ __u32 alignment;
-+ __u32 cow_format;
-+ char backing_file[PATH_LEN_V3];
-+};
-+
-+/* COW format definitions - for now, we have only the usual COW bitmap */
-+#define COW_BITMAP 0
-+
-+union cow_header {
-+ struct cow_header_v1 v1;
-+ struct cow_header_v2 v2;
-+ struct cow_header_v3 v3;
-+};
-+
-+#define COW_MAGIC 0x4f4f4f4d /* MOOO */
-+#define COW_VERSION 3
-+
-+#define DIV_ROUND(x, len) (((x) + (len) - 1) / (len))
-+#define ROUND_UP(x, align) DIV_ROUND(x, align) * (align)
-+
-+void cow_sizes(int version, __u64 size, int sectorsize, int align,
-+ int bitmap_offset, unsigned long *bitmap_len_out,
-+ int *data_offset_out)
-+{
-+ if(version < 3){
-+ *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
-+
-+ *data_offset_out = bitmap_offset + *bitmap_len_out;
-+ *data_offset_out = (*data_offset_out + sectorsize - 1) /
-+ sectorsize;
-+ *data_offset_out *= sectorsize;
-+ }
-+ else {
-+ *bitmap_len_out = DIV_ROUND(size, sectorsize);
-+ *bitmap_len_out = DIV_ROUND(*bitmap_len_out, 8);
-+
-+ *data_offset_out = bitmap_offset + *bitmap_len_out;
-+ *data_offset_out = ROUND_UP(*data_offset_out, align);
-+ }
-+}
-+
-+static int absolutize(char *to, int size, char *from)
-+{
-+ char save_cwd[256], *slash;
-+ int remaining;
-+
-+ if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
-+ cow_printf("absolutize : unable to get cwd - errno = %d\n",
-+ errno);
-+ return(-1);
-+ }
-+ slash = strrchr(from, '/');
-+ if(slash != NULL){
-+ *slash = '\0';
-+ if(chdir(from)){
-+ *slash = '/';
-+ cow_printf("absolutize : Can't cd to '%s' - "
-+ "errno = %d\n", from, errno);
-+ return(-1);
-+ }
-+ *slash = '/';
-+ if(getcwd(to, size) == NULL){
-+ cow_printf("absolutize : unable to get cwd of '%s' - "
-+ "errno = %d\n", from, errno);
-+ return(-1);
-+ }
-+ remaining = size - strlen(to);
-+ if(strlen(slash) + 1 > remaining){
-+ cow_printf("absolutize : unable to fit '%s' into %d "
-+ "chars\n", from, size);
-+ return(-1);
-+ }
-+ strcat(to, slash);
-+ }
-+ else {
-+ if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){
-+ cow_printf("absolutize : unable to fit '%s' into %d "
-+ "chars\n", from, size);
-+ return(-1);
-+ }
-+ strcpy(to, save_cwd);
-+ strcat(to, "/");
-+ strcat(to, from);
-+ }
-+ chdir(save_cwd);
-+ return(0);
-+}
-+
-+int write_cow_header(char *cow_file, int fd, char *backing_file,
-+ int sectorsize, int alignment, long long *size)
-+{
-+ struct cow_header_v3 *header;
-+ unsigned long modtime;
-+ int err;
-+
-+ err = cow_seek_file(fd, 0);
-+ if(err < 0){
-+ cow_printf("write_cow_header - lseek failed, err = %d\n", -err);
-+ goto out;
-+ }
-+
-+ err = -ENOMEM;
-+ header = cow_malloc(sizeof(*header));
-+ if(header == NULL){
-+ cow_printf("Failed to allocate COW V3 header\n");
-+ goto out;
-+ }
-+ header->magic = htonl(COW_MAGIC);
-+ header->version = htonl(COW_VERSION);
-+
-+ err = -EINVAL;
-+ if(strlen(backing_file) > sizeof(header->backing_file) - 1){
-+ cow_printf("Backing file name \"%s\" is too long - names are "
-+ "limited to %d characters\n", backing_file,
-+ sizeof(header->backing_file) - 1);
-+ goto out_free;
-+ }
-+
-+ if(absolutize(header->backing_file, sizeof(header->backing_file),
-+ backing_file))
-+ goto out_free;
-+
-+ err = os_file_modtime(header->backing_file, &modtime);
-+ if(err < 0){
-+ cow_printf("Backing file '%s' mtime request failed, "
-+ "err = %d\n", header->backing_file, -err);
-+ goto out_free;
-+ }
-+
-+ err = cow_file_size(header->backing_file, size);
-+ if(err < 0){
-+ cow_printf("Couldn't get size of backing file '%s', "
-+ "err = %d\n", header->backing_file, -err);
-+ goto out_free;
-+ }
-+
-+ header->mtime = htonl(modtime);
-+ header->size = htonll(*size);
-+ header->sectorsize = htonl(sectorsize);
-+ header->alignment = htonl(alignment);
-+ header->cow_format = COW_BITMAP;
-+
-+ err = os_write_file(fd, header, sizeof(*header));
-+ if(err != sizeof(*header)){
-+ cow_printf("Write of header to new COW file '%s' failed, "
-+ "err = %d\n", cow_file, -err);
-+ goto out_free;
-+ }
-+ err = 0;
-+ out_free:
-+ cow_free(header);
-+ out:
-+ return(err);
-+}
-+
-+int file_reader(__u64 offset, char *buf, int len, void *arg)
-+{
-+ int fd = *((int *) arg);
-+
-+ return(pread(fd, buf, len, offset));
-+}
-+
-+/* XXX Need to sanity-check the values read from the header */
-+
-+int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
-+ __u32 *version_out, char **backing_file_out,
-+ time_t *mtime_out, __u64 *size_out,
-+ int *sectorsize_out, __u32 *align_out,
-+ int *bitmap_offset_out)
-+{
-+ union cow_header *header;
-+ char *file;
-+ int err, n;
-+ unsigned long version, magic;
-+
-+ header = cow_malloc(sizeof(*header));
-+ if(header == NULL){
-+ cow_printf("read_cow_header - Failed to allocate header\n");
-+ return(-ENOMEM);
-+ }
-+ err = -EINVAL;
-+ n = (*reader)(0, (char *) header, sizeof(*header), arg);
-+ if(n < offsetof(typeof(header->v1), backing_file)){
-+ cow_printf("read_cow_header - short header\n");
-+ goto out;
-+ }
-+
-+ magic = header->v1.magic;
-+ if(magic == COW_MAGIC) {
-+ version = header->v1.version;
-+ }
-+ else if(magic == ntohl(COW_MAGIC)){
-+ version = ntohl(header->v1.version);
-+ }
-+ /* No error printed because the non-COW case comes through here */
-+ else goto out;
-+
-+ *version_out = version;
-+
-+ if(version == 1){
-+ if(n < sizeof(header->v1)){
-+ cow_printf("read_cow_header - failed to read V1 "
-+ "header\n");
-+ goto out;
-+ }
-+ *mtime_out = header->v1.mtime;
-+ *size_out = header->v1.size;
-+ *sectorsize_out = header->v1.sectorsize;
-+ *bitmap_offset_out = sizeof(header->v1);
-+ *align_out = *sectorsize_out;
-+ file = header->v1.backing_file;
-+ }
-+ else if(version == 2){
-+ if(n < sizeof(header->v2)){
-+ cow_printf("read_cow_header - failed to read V2 "
-+ "header\n");
-+ goto out;
-+ }
-+ *mtime_out = ntohl(header->v2.mtime);
-+ *size_out = ntohll(header->v2.size);
-+ *sectorsize_out = ntohl(header->v2.sectorsize);
-+ *bitmap_offset_out = sizeof(header->v2);
-+ *align_out = *sectorsize_out;
-+ file = header->v2.backing_file;
-+ }
-+ else if(version == 3){
-+ if(n < sizeof(header->v3)){
-+ cow_printf("read_cow_header - failed to read V2 "
-+ "header\n");
-+ goto out;
-+ }
-+ *mtime_out = ntohl(header->v3.mtime);
-+ *size_out = ntohll(header->v3.size);
-+ *sectorsize_out = ntohl(header->v3.sectorsize);
-+ *align_out = ntohl(header->v3.alignment);
-+ *bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out);
-+ file = header->v3.backing_file;
-+ }
-+ else {
-+ cow_printf("read_cow_header - invalid COW version\n");
-+ goto out;
-+ }
-+ err = -ENOMEM;
-+ *backing_file_out = cow_strdup(file);
-+ if(*backing_file_out == NULL){
-+ cow_printf("read_cow_header - failed to allocate backing "
-+ "file\n");
-+ goto out;
-+ }
-+ err = 0;
-+ out:
-+ cow_free(header);
-+ return(err);
-+}
-+
-+int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize,
-+ int alignment, int *bitmap_offset_out,
-+ unsigned long *bitmap_len_out, int *data_offset_out)
-+{
-+ __u64 size, offset;
-+ char zero = 0;
-+ int err;
-+
-+ err = write_cow_header(cow_file, fd, backing_file, sectorsize,
-+ alignment, &size);
-+ if(err)
-+ goto out;
-+
-+ *bitmap_offset_out = ROUND_UP(sizeof(struct cow_header_v3), alignment);
-+ cow_sizes(COW_VERSION, size, sectorsize, alignment, *bitmap_offset_out,
-+ bitmap_len_out, data_offset_out);
-+
-+ offset = *data_offset_out + size - sizeof(zero);
-+ err = cow_seek_file(fd, offset);
-+ if(err < 0){
-+ cow_printf("cow bitmap lseek failed : err = %d\n", -err);
-+ goto out;
-+ }
-+
-+ /* does not really matter how much we write it is just to set EOF
-+ * this also sets the entire COW bitmap
-+ * to zero without having to allocate it
-+ */
-+ err = cow_write_file(fd, &zero, sizeof(zero));
-+ if(err != sizeof(zero)){
-+ cow_printf("Write of bitmap to new COW file '%s' failed, "
-+ "err = %d\n", cow_file, -err);
-+ err = -EINVAL;
-+ goto out;
-+ }
-+
-+ return(0);
-+
-+ out:
-+ return(err);
-+}
-+
-+/*
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/daemon.h um/arch/um/drivers/daemon.h
---- orig/arch/um/drivers/daemon.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/daemon.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,35 @@
-+/*
-+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "net_user.h"
-+
-+#define SWITCH_VERSION 3
-+
-+struct daemon_data {
-+ char *sock_type;
-+ char *ctl_sock;
-+ void *ctl_addr;
-+ void *data_addr;
-+ void *local_addr;
-+ int fd;
-+ int control;
-+ void *dev;
-+};
-+
-+extern struct net_user_info daemon_user_info;
-+
-+extern int daemon_user_write(int fd, void *buf, int len,
-+ struct daemon_data *pri);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/daemon_kern.c um/arch/um/drivers/daemon_kern.c
---- orig/arch/um/drivers/daemon_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/daemon_kern.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,113 @@
-+/*
-+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
-+ * James Leu (jleu@mindspring.net).
-+ * Copyright (C) 2001 by various other people who didn't put their name here.
-+ * Licensed under the GPL.
-+ */
-+
-+#include "linux/kernel.h"
-+#include "linux/init.h"
-+#include "linux/netdevice.h"
-+#include "linux/etherdevice.h"
-+#include "net_kern.h"
-+#include "net_user.h"
-+#include "daemon.h"
-+
-+struct daemon_init {
-+ char *sock_type;
-+ char *ctl_sock;
-+};
-+
-+void daemon_init(struct net_device *dev, void *data)
-+{
-+ struct uml_net_private *pri;
-+ struct daemon_data *dpri;
-+ struct daemon_init *init = data;
-+
-+ init_etherdev(dev, 0);
-+ pri = dev->priv;
-+ dpri = (struct daemon_data *) pri->user;
-+ *dpri = ((struct daemon_data)
-+ { .sock_type = init->sock_type,
-+ .ctl_sock = init->ctl_sock,
-+ .ctl_addr = NULL,
-+ .data_addr = NULL,
-+ .local_addr = NULL,
-+ .fd = -1,
-+ .control = -1,
-+ .dev = dev });
-+
-+ printk("daemon backend (uml_switch version %d) - %s:%s",
-+ SWITCH_VERSION, dpri->sock_type, dpri->ctl_sock);
-+ printk("\n");
-+}
-+
-+static int daemon_read(int fd, struct sk_buff **skb,
-+ struct uml_net_private *lp)
-+{
-+ *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER);
-+ if(*skb == NULL) return(-ENOMEM);
-+ return(net_recvfrom(fd, (*skb)->mac.raw,
-+ (*skb)->dev->mtu + ETH_HEADER_OTHER));
-+}
-+
-+static int daemon_write(int fd, struct sk_buff **skb,
-+ struct uml_net_private *lp)
-+{
-+ return(daemon_user_write(fd, (*skb)->data, (*skb)->len,
-+ (struct daemon_data *) &lp->user));
-+}
-+
-+static struct net_kern_info daemon_kern_info = {
-+ .init = daemon_init,
-+ .protocol = eth_protocol,
-+ .read = daemon_read,
-+ .write = daemon_write,
-+};
-+
-+int daemon_setup(char *str, char **mac_out, void *data)
-+{
-+ struct daemon_init *init = data;
-+ char *remain;
-+
-+ *init = ((struct daemon_init)
-+ { .sock_type = "unix",
-+ .ctl_sock = "/tmp/uml.ctl" });
-+
-+ remain = split_if_spec(str, mac_out, &init->sock_type, &init->ctl_sock,
-+ NULL);
-+ if(remain != NULL)
-+ printk(KERN_WARNING "daemon_setup : Ignoring data socket "
-+ "specification\n");
-+
-+ return(1);
-+}
-+
-+static struct transport daemon_transport = {
-+ .list = LIST_HEAD_INIT(daemon_transport.list),
-+ .name = "daemon",
-+ .setup = daemon_setup,
-+ .user = &daemon_user_info,
-+ .kern = &daemon_kern_info,
-+ .private_size = sizeof(struct daemon_data),
-+ .setup_size = sizeof(struct daemon_init),
-+};
-+
-+static int register_daemon(void)
-+{
-+ register_transport(&daemon_transport);
-+ return(1);
-+}
-+
-+__initcall(register_daemon);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/daemon_user.c um/arch/um/drivers/daemon_user.c
---- orig/arch/um/drivers/daemon_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/daemon_user.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,197 @@
-+/*
-+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
-+ * James Leu (jleu@mindspring.net).
-+ * Copyright (C) 2001 by various other people who didn't put their name here.
-+ * Licensed under the GPL.
-+ */
-+
-+#include <errno.h>
-+#include <unistd.h>
-+#include <stdint.h>
-+#include <sys/socket.h>
-+#include <sys/un.h>
-+#include <sys/time.h>
-+#include "net_user.h"
-+#include "daemon.h"
-+#include "kern_util.h"
-+#include "user_util.h"
-+#include "user.h"
-+#include "os.h"
-+
-+#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
-+
-+enum request_type { REQ_NEW_CONTROL };
-+
-+#define SWITCH_MAGIC 0xfeedface
-+
-+struct request_v3 {
-+ uint32_t magic;
-+ uint32_t version;
-+ enum request_type type;
-+ struct sockaddr_un sock;
-+};
-+
-+static struct sockaddr_un *new_addr(void *name, int len)
-+{
-+ struct sockaddr_un *sun;
-+
-+ sun = um_kmalloc(sizeof(struct sockaddr_un));
-+ if(sun == NULL){
-+ printk("new_addr: allocation of sockaddr_un failed\n");
-+ return(NULL);
-+ }
-+ sun->sun_family = AF_UNIX;
-+ memcpy(sun->sun_path, name, len);
-+ return(sun);
-+}
-+
-+static int connect_to_switch(struct daemon_data *pri)
-+{
-+ struct sockaddr_un *ctl_addr = pri->ctl_addr;
-+ struct sockaddr_un *local_addr = pri->local_addr;
-+ struct sockaddr_un *sun;
-+ struct request_v3 req;
-+ int fd, n, err;
-+
-+ pri->control = socket(AF_UNIX, SOCK_STREAM, 0);
-+ if(pri->control < 0){
-+ printk("daemon_open : control socket failed, errno = %d\n",
-+ errno);
-+ return(-errno);
-+ }
-+
-+ if(connect(pri->control, (struct sockaddr *) ctl_addr,
-+ sizeof(*ctl_addr)) < 0){
-+ printk("daemon_open : control connect failed, errno = %d\n",
-+ errno);
-+ err = -errno;
-+ goto out;
-+ }
-+
-+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
-+ if(fd < 0){
-+ printk("daemon_open : data socket failed, errno = %d\n",
-+ errno);
-+ err = -errno;
-+ goto out;
-+ }
-+ if(bind(fd, (struct sockaddr *) local_addr, sizeof(*local_addr)) < 0){
-+ printk("daemon_open : data bind failed, errno = %d\n",
-+ errno);
-+ err = -errno;
-+ goto out_close;
-+ }
-+
-+ sun = um_kmalloc(sizeof(struct sockaddr_un));
-+ if(sun == NULL){
-+ printk("new_addr: allocation of sockaddr_un failed\n");
-+ err = -ENOMEM;
-+ goto out_close;
-+ }
-+
-+ req.magic = SWITCH_MAGIC;
-+ req.version = SWITCH_VERSION;
-+ req.type = REQ_NEW_CONTROL;
-+ req.sock = *local_addr;
-+ n = os_write_file(pri->control, &req, sizeof(req));
-+ if(n != sizeof(req)){
-+ printk("daemon_open : control setup request failed, err = %d\n",
-+ -n);
-+ err = -ENOTCONN;
-+ goto out;
-+ }
-+
-+ n = os_read_file(pri->control, sun, sizeof(*sun));
-+ if(n != sizeof(*sun)){
-+ printk("daemon_open : read of data socket failed, err = %d\n",
-+ -n);
-+ err = -ENOTCONN;
-+ goto out_close;
-+ }
-+
-+ pri->data_addr = sun;
-+ return(fd);
-+
-+ out_close:
-+ os_close_file(fd);
-+ out:
-+ os_close_file(pri->control);
-+ return(err);
-+}
-+
-+static void daemon_user_init(void *data, void *dev)
-+{
-+ struct daemon_data *pri = data;
-+ struct timeval tv;
-+ struct {
-+ char zero;
-+ int pid;
-+ int usecs;
-+ } name;
-+
-+ if(!strcmp(pri->sock_type, "unix"))
-+ pri->ctl_addr = new_addr(pri->ctl_sock,
-+ strlen(pri->ctl_sock) + 1);
-+ name.zero = 0;
-+ name.pid = os_getpid();
-+ gettimeofday(&tv, NULL);
-+ name.usecs = tv.tv_usec;
-+ pri->local_addr = new_addr(&name, sizeof(name));
-+ pri->dev = dev;
-+ pri->fd = connect_to_switch(pri);
-+ if(pri->fd < 0){
-+ kfree(pri->local_addr);
-+ pri->local_addr = NULL;
-+ }
-+}
-+
-+static int daemon_open(void *data)
-+{
-+ struct daemon_data *pri = data;
-+ return(pri->fd);
-+}
-+
-+static void daemon_remove(void *data)
-+{
-+ struct daemon_data *pri = data;
-+
-+ os_close_file(pri->fd);
-+ os_close_file(pri->control);
-+ if(pri->data_addr != NULL) kfree(pri->data_addr);
-+ if(pri->ctl_addr != NULL) kfree(pri->ctl_addr);
-+ if(pri->local_addr != NULL) kfree(pri->local_addr);
-+}
-+
-+int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri)
-+{
-+ struct sockaddr_un *data_addr = pri->data_addr;
-+
-+ return(net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)));
-+}
-+
-+static int daemon_set_mtu(int mtu, void *data)
-+{
-+ return(mtu);
-+}
-+
-+struct net_user_info daemon_user_info = {
-+ .init = daemon_user_init,
-+ .open = daemon_open,
-+ .close = NULL,
-+ .remove = daemon_remove,
-+ .set_mtu = daemon_set_mtu,
-+ .add_address = NULL,
-+ .delete_address = NULL,
-+ .max_packet = MAX_PACKET - ETH_HEADER_OTHER
-+};
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/fd.c um/arch/um/drivers/fd.c
---- orig/arch/um/drivers/fd.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/fd.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,97 @@
-+/*
-+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <termios.h>
-+#include "user.h"
-+#include "user_util.h"
-+#include "chan_user.h"
-+
-+struct fd_chan {
-+ int fd;
-+ int raw;
-+ struct termios tt;
-+ char str[sizeof("1234567890\0")];
-+};
-+
-+void *fd_init(char *str, int device, struct chan_opts *opts)
-+{
-+ struct fd_chan *data;
-+ char *end;
-+ int n;
-+
-+ if(*str != ':'){
-+ printk("fd_init : channel type 'fd' must specify a file "
-+ "descriptor\n");
-+ return(NULL);
-+ }
-+ str++;
-+ n = strtoul(str, &end, 0);
-+ if((*end != '\0') || (end == str)){
-+ printk("fd_init : couldn't parse file descriptor '%s'\n", str);
-+ return(NULL);
-+ }
-+ data = um_kmalloc(sizeof(*data));
-+ if(data == NULL) return(NULL);
-+ *data = ((struct fd_chan) { .fd = n,
-+ .raw = opts->raw });
-+ return(data);
-+}
-+
-+int fd_open(int input, int output, int primary, void *d, char **dev_out)
-+{
-+ struct fd_chan *data = d;
-+
-+ if(data->raw && isatty(data->fd)){
-+ tcgetattr(data->fd, &data->tt);
-+ raw(data->fd, 0);
-+ }
-+ sprintf(data->str, "%d", data->fd);
-+ *dev_out = data->str;
-+ return(data->fd);
-+}
-+
-+void fd_close(int fd, void *d)
-+{
-+ struct fd_chan *data = d;
-+
-+ if(data->raw && isatty(fd)){
-+ tcsetattr(fd, TCSAFLUSH, &data->tt);
-+ data->raw = 0;
-+ }
-+}
-+
-+int fd_console_write(int fd, const char *buf, int n, void *d)
-+{
-+ struct fd_chan *data = d;
-+
-+ return(generic_console_write(fd, buf, n, &data->tt));
-+}
-+
-+struct chan_ops fd_ops = {
-+ .type = "fd",
-+ .init = fd_init,
-+ .open = fd_open,
-+ .close = fd_close,
-+ .read = generic_read,
-+ .write = generic_write,
-+ .console_write = fd_console_write,
-+ .window_size = generic_window_size,
-+ .free = generic_free,
-+ .winch = 1,
-+};
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/harddog_kern.c um/arch/um/drivers/harddog_kern.c
---- orig/arch/um/drivers/harddog_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/harddog_kern.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,194 @@
-+/* UML hardware watchdog, shamelessly stolen from:
-+ *
-+ * SoftDog 0.05: A Software Watchdog Device
-+ *
-+ * (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
-+ * http://www.redhat.com
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
-+ * warranty for any of this software. This material is provided
-+ * "AS-IS" and at no charge.
-+ *
-+ * (c) Copyright 1995 Alan Cox <alan@lxorguk.ukuu.org.uk>
-+ *
-+ * Software only watchdog driver. Unlike its big brother the WDT501P
-+ * driver this won't always recover a failed machine.
-+ *
-+ * 03/96: Angelo Haritsis <ah@doc.ic.ac.uk> :
-+ * Modularised.
-+ * Added soft_margin; use upon insmod to change the timer delay.
-+ * NB: uses same minor as wdt (WATCHDOG_MINOR); we could use separate
-+ * minors.
-+ *
-+ * 19980911 Alan Cox
-+ * Made SMP safe for 2.3.x
-+ *
-+ * 20011127 Joel Becker (jlbec@evilplan.org>
-+ * Added soft_noboot; Allows testing the softdog trigger without
-+ * requiring a recompile.
-+ * Added WDIOC_GETTIMEOUT and WDIOC_SETTIMOUT.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/config.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/fs.h>
-+#include <linux/mm.h>
-+#include <linux/miscdevice.h>
-+#include <linux/watchdog.h>
-+#include <linux/reboot.h>
-+#include <linux/smp_lock.h>
-+#include <linux/init.h>
-+#include <asm/uaccess.h>
-+#include "helper.h"
-+#include "mconsole.h"
-+
-+MODULE_LICENSE("GPL");
-+
-+/* Locked by the BKL in harddog_open and harddog_release */
-+static int timer_alive;
-+static int harddog_in_fd = -1;
-+static int harddog_out_fd = -1;
-+
-+/*
-+ * Allow only one person to hold it open
-+ */
-+
-+extern int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock);
-+
-+static int harddog_open(struct inode *inode, struct file *file)
-+{
-+ int err;
-+ char *sock = NULL;
-+
-+ lock_kernel();
-+ if(timer_alive)
-+ return -EBUSY;
-+#ifdef CONFIG_HARDDOG_NOWAYOUT
-+ MOD_INC_USE_COUNT;
-+#endif
-+
-+#ifdef CONFIG_MCONSOLE
-+ sock = mconsole_notify_socket();
-+#endif
-+ err = start_watchdog(&harddog_in_fd, &harddog_out_fd, sock);
-+ if(err) return(err);
-+
-+ timer_alive = 1;
-+ unlock_kernel();
-+ return 0;
-+}
-+
-+extern void stop_watchdog(int in_fd, int out_fd);
-+
-+static int harddog_release(struct inode *inode, struct file *file)
-+{
-+ /*
-+ * Shut off the timer.
-+ */
-+ lock_kernel();
-+
-+ stop_watchdog(harddog_in_fd, harddog_out_fd);
-+ harddog_in_fd = -1;
-+ harddog_out_fd = -1;
-+
-+ timer_alive=0;
-+ unlock_kernel();
-+ return 0;
-+}
-+
-+extern int ping_watchdog(int fd);
-+
-+static ssize_t harddog_write(struct file *file, const char *data, size_t len,
-+ loff_t *ppos)
-+{
-+ /* Can't seek (pwrite) on this device */
-+ if (ppos != &file->f_pos)
-+ return -ESPIPE;
-+
-+ /*
-+ * Refresh the timer.
-+ */
-+ if(len)
-+ return(ping_watchdog(harddog_out_fd));
-+ return 0;
-+}
-+
-+static int harddog_ioctl(struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ static struct watchdog_info ident = {
-+ WDIOF_SETTIMEOUT,
-+ 0,
-+ "UML Hardware Watchdog"
-+ };
-+ switch (cmd) {
-+ default:
-+ return -ENOTTY;
-+ case WDIOC_GETSUPPORT:
-+ if(copy_to_user((struct harddog_info *)arg, &ident,
-+ sizeof(ident)))
-+ return -EFAULT;
-+ return 0;
-+ case WDIOC_GETSTATUS:
-+ case WDIOC_GETBOOTSTATUS:
-+ return put_user(0,(int *)arg);
-+ case WDIOC_KEEPALIVE:
-+ return(ping_watchdog(harddog_out_fd));
-+ }
-+}
-+
-+static struct file_operations harddog_fops = {
-+ .owner = THIS_MODULE,
-+ .write = harddog_write,
-+ .ioctl = harddog_ioctl,
-+ .open = harddog_open,
-+ .release = harddog_release,
-+};
-+
-+static struct miscdevice harddog_miscdev = {
-+ .minor = WATCHDOG_MINOR,
-+ .name = "watchdog",
-+ .fops = &harddog_fops,
-+};
-+
-+static char banner[] __initdata = KERN_INFO "UML Watchdog Timer\n";
-+
-+static int __init harddog_init(void)
-+{
-+ int ret;
-+
-+ ret = misc_register(&harddog_miscdev);
-+
-+ if (ret)
-+ return ret;
-+
-+ printk(banner);
-+
-+ return(0);
-+}
-+
-+static void __exit harddog_exit(void)
-+{
-+ misc_deregister(&harddog_miscdev);
-+}
-+
-+module_init(harddog_init);
-+module_exit(harddog_exit);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/harddog_user.c um/arch/um/drivers/harddog_user.c
---- orig/arch/um/drivers/harddog_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/harddog_user.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,143 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdio.h>
-+#include <unistd.h>
-+#include <errno.h>
-+#include "user_util.h"
-+#include "user.h"
-+#include "helper.h"
-+#include "mconsole.h"
-+#include "os.h"
-+#include "choose-mode.h"
-+#include "mode.h"
-+
-+struct dog_data {
-+ int stdin;
-+ int stdout;
-+ int close_me[2];
-+};
-+
-+static void pre_exec(void *d)
-+{
-+ struct dog_data *data = d;
-+
-+ dup2(data->stdin, 0);
-+ dup2(data->stdout, 1);
-+ dup2(data->stdout, 2);
-+ os_close_file(data->stdin);
-+ os_close_file(data->stdout);
-+ os_close_file(data->close_me[0]);
-+ os_close_file(data->close_me[1]);
-+}
-+
-+int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
-+{
-+ struct dog_data data;
-+ int in_fds[2], out_fds[2], pid, n, err;
-+ char pid_buf[sizeof("nnnnn\0")], c;
-+ char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL };
-+ char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL,
-+ NULL };
-+ char **args = NULL;
-+
-+ err = os_pipe(in_fds, 1, 0);
-+ if(err < 0){
-+ printk("harddog_open - os_pipe failed, err = %d\n", -err);
-+ goto out;
-+ }
-+
-+ err = os_pipe(out_fds, 1, 0);
-+ if(err < 0){
-+ printk("harddog_open - os_pipe failed, err = %d\n", -err);
-+ goto out_close_in;
-+ }
-+
-+ data.stdin = out_fds[0];
-+ data.stdout = in_fds[1];
-+ data.close_me[0] = out_fds[1];
-+ data.close_me[1] = in_fds[0];
-+
-+ if(sock != NULL){
-+ mconsole_args[2] = sock;
-+ args = mconsole_args;
-+ }
-+ else {
-+ /* XXX The os_getpid() is not SMP correct */
-+ sprintf(pid_buf, "%d", CHOOSE_MODE(tracing_pid, os_getpid()));
-+ args = pid_args;
-+ }
-+
-+ pid = run_helper(pre_exec, &data, args, NULL);
-+
-+ os_close_file(out_fds[0]);
-+ os_close_file(in_fds[1]);
-+
-+ if(pid < 0){
-+ err = -pid;
-+ printk("harddog_open - run_helper failed, errno = %d\n", -err);
-+ goto out_close_out;
-+ }
-+
-+ n = os_read_file(in_fds[0], &c, sizeof(c));
-+ if(n == 0){
-+ printk("harddog_open - EOF on watchdog pipe\n");
-+ helper_wait(pid);
-+ err = -EIO;
-+ goto out_close_out;
-+ }
-+ else if(n < 0){
-+ printk("harddog_open - read of watchdog pipe failed, "
-+ "err = %d\n", -n);
-+ helper_wait(pid);
-+ err = n;
-+ goto out_close_out;
-+ }
-+ *in_fd_ret = in_fds[0];
-+ *out_fd_ret = out_fds[1];
-+ return(0);
-+
-+ out_close_in:
-+ os_close_file(in_fds[0]);
-+ os_close_file(in_fds[1]);
-+ out_close_out:
-+ os_close_file(out_fds[0]);
-+ os_close_file(out_fds[1]);
-+ out:
-+ return(err);
-+}
-+
-+void stop_watchdog(int in_fd, int out_fd)
-+{
-+ os_close_file(in_fd);
-+ os_close_file(out_fd);
-+}
-+
-+int ping_watchdog(int fd)
-+{
-+ int n;
-+ char c = '\n';
-+
-+ n = os_write_file(fd, &c, sizeof(c));
-+ if(n != sizeof(c)){
-+ printk("ping_watchdog - write failed, err = %d\n", -n);
-+ if(n < 0)
-+ return(n);
-+ return(-EIO);
-+ }
-+ return 1;
-+
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/hostaudio_kern.c um/arch/um/drivers/hostaudio_kern.c
---- orig/arch/um/drivers/hostaudio_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/hostaudio_kern.c 2004-02-12 05:46:22.000000000 -0500
-@@ -0,0 +1,352 @@
-+/*
-+ * Copyright (C) 2002 Steve Schmidtke
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/config.h"
-+#include "linux/module.h"
-+#include "linux/init.h"
-+#include "linux/slab.h"
-+#include "linux/fs.h"
-+#include "linux/sound.h"
-+#include "linux/soundcard.h"
-+#include "asm/uaccess.h"
-+#include "kern_util.h"
-+#include "init.h"
-+#include "os.h"
-+
-+struct hostaudio_state {
-+ int fd;
-+};
-+
-+struct hostmixer_state {
-+ int fd;
-+};
-+
-+#define HOSTAUDIO_DEV_DSP "/dev/sound/dsp"
-+#define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer"
-+
-+/* Only changed from linux_main at boot time */
-+char *dsp = HOSTAUDIO_DEV_DSP;
-+char *mixer = HOSTAUDIO_DEV_MIXER;
-+
-+#define DSP_HELP \
-+" This is used to specify the host dsp device to the hostaudio driver.\n" \
-+" The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n"
-+
-+#define MIXER_HELP \
-+" This is used to specify the host mixer device to the hostaudio driver.\n" \
-+" The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n"
-+
-+#ifndef MODULE
-+static int set_dsp(char *name, int *add)
-+{
-+ dsp = name;
-+ return(0);
-+}
-+
-+__uml_setup("dsp=", set_dsp, "dsp=<dsp device>\n" DSP_HELP);
-+
-+static int set_mixer(char *name, int *add)
-+{
-+ mixer = name;
-+ return(0);
-+}
-+
-+__uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP);
-+
-+#else /*MODULE*/
-+
-+MODULE_PARM(dsp, "s");
-+MODULE_PARM_DESC(dsp, DSP_HELP);
-+
-+MODULE_PARM(mixer, "s");
-+MODULE_PARM_DESC(mixer, MIXER_HELP);
-+
-+#endif
-+
-+/* /dev/dsp file operations */
-+
-+static ssize_t hostaudio_read(struct file *file, char *buffer, size_t count,
-+ loff_t *ppos)
-+{
-+ struct hostaudio_state *state = file->private_data;
-+ void *kbuf;
-+ int err;
-+
-+#ifdef DEBUG
-+ printk("hostaudio: read called, count = %d\n", count);
-+#endif
-+
-+ kbuf = kmalloc(count, GFP_KERNEL);
-+ if(kbuf == NULL)
-+ return(-ENOMEM);
-+
-+ err = os_read_file(state->fd, kbuf, count);
-+ if(err < 0)
-+ goto out;
-+
-+ if(copy_to_user(buffer, kbuf, err))
-+ err = -EFAULT;
-+
-+ out:
-+ kfree(kbuf);
-+ return(err);
-+}
-+
-+static ssize_t hostaudio_write(struct file *file, const char *buffer,
-+ size_t count, loff_t *ppos)
-+{
-+ struct hostaudio_state *state = file->private_data;
-+ void *kbuf;
-+ int err;
-+
-+#ifdef DEBUG
-+ printk("hostaudio: write called, count = %d\n", count);
-+#endif
-+
-+ kbuf = kmalloc(count, GFP_KERNEL);
-+ if(kbuf == NULL)
-+ return(-ENOMEM);
-+
-+ err = -EFAULT;
-+ if(copy_from_user(kbuf, buffer, count))
-+ goto out;
-+
-+ err = os_write_file(state->fd, kbuf, count);
-+ if(err < 0)
-+ goto out;
-+ *ppos += err;
-+
-+ out:
-+ kfree(kbuf);
-+ return(err);
-+}
-+
-+static unsigned int hostaudio_poll(struct file *file,
-+ struct poll_table_struct *wait)
-+{
-+ unsigned int mask = 0;
-+
-+#ifdef DEBUG
-+ printk("hostaudio: poll called (unimplemented)\n");
-+#endif
-+
-+ return(mask);
-+}
-+
-+static int hostaudio_ioctl(struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ struct hostaudio_state *state = file->private_data;
-+ unsigned long data = 0;
-+ int err;
-+
-+#ifdef DEBUG
-+ printk("hostaudio: ioctl called, cmd = %u\n", cmd);
-+#endif
-+ switch(cmd){
-+ case SNDCTL_DSP_SPEED:
-+ case SNDCTL_DSP_STEREO:
-+ case SNDCTL_DSP_GETBLKSIZE:
-+ case SNDCTL_DSP_CHANNELS:
-+ case SNDCTL_DSP_SUBDIVIDE:
-+ case SNDCTL_DSP_SETFRAGMENT:
-+ if(get_user(data, (int *) arg))
-+ return(-EFAULT);
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ err = os_ioctl_generic(state->fd, cmd, (unsigned long) &data);
-+
-+ switch(cmd){
-+ case SNDCTL_DSP_SPEED:
-+ case SNDCTL_DSP_STEREO:
-+ case SNDCTL_DSP_GETBLKSIZE:
-+ case SNDCTL_DSP_CHANNELS:
-+ case SNDCTL_DSP_SUBDIVIDE:
-+ case SNDCTL_DSP_SETFRAGMENT:
-+ if(put_user(data, (int *) arg))
-+ return(-EFAULT);
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ return(err);
-+}
-+
-+static int hostaudio_open(struct inode *inode, struct file *file)
-+{
-+ struct hostaudio_state *state;
-+ int r = 0, w = 0;
-+ int ret;
-+
-+#ifdef DEBUG
-+ printk("hostaudio: open called (host: %s)\n", dsp);
-+#endif
-+
-+ state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL);
-+ if(state == NULL)
-+ return(-ENOMEM);
-+
-+ if(file->f_mode & FMODE_READ) r = 1;
-+ if(file->f_mode & FMODE_WRITE) w = 1;
-+
-+ ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
-+ if(ret < 0){
-+ kfree(state);
-+ return(ret);
-+ }
-+
-+ state->fd = ret;
-+ file->private_data = state;
-+ return(0);
-+}
-+
-+static int hostaudio_release(struct inode *inode, struct file *file)
-+{
-+ struct hostaudio_state *state = file->private_data;
-+
-+#ifdef DEBUG
-+ printk("hostaudio: release called\n");
-+#endif
-+
-+ os_close_file(state->fd);
-+ kfree(state);
-+
-+ return(0);
-+}
-+
-+/* /dev/mixer file operations */
-+
-+static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ struct hostmixer_state *state = file->private_data;
-+
-+#ifdef DEBUG
-+ printk("hostmixer: ioctl called\n");
-+#endif
-+
-+ return(os_ioctl_generic(state->fd, cmd, arg));
-+}
-+
-+static int hostmixer_open_mixdev(struct inode *inode, struct file *file)
-+{
-+ struct hostmixer_state *state;
-+ int r = 0, w = 0;
-+ int ret;
-+
-+#ifdef DEBUG
-+ printk("hostmixer: open called (host: %s)\n", mixer);
-+#endif
-+
-+ state = kmalloc(sizeof(struct hostmixer_state), GFP_KERNEL);
-+ if(state == NULL) return(-ENOMEM);
-+
-+ if(file->f_mode & FMODE_READ) r = 1;
-+ if(file->f_mode & FMODE_WRITE) w = 1;
-+
-+ ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
-+
-+ if(ret < 0){
-+ printk("hostaudio_open_mixdev failed to open '%s', err = %d\n",
-+ dsp, -ret);
-+ kfree(state);
-+ return(ret);
-+ }
-+
-+ file->private_data = state;
-+ return(0);
-+}
-+
-+static int hostmixer_release(struct inode *inode, struct file *file)
-+{
-+ struct hostmixer_state *state = file->private_data;
-+
-+#ifdef DEBUG
-+ printk("hostmixer: release called\n");
-+#endif
-+
-+ os_close_file(state->fd);
-+ kfree(state);
-+
-+ return(0);
-+}
-+
-+
-+/* kernel module operations */
-+
-+static struct file_operations hostaudio_fops = {
-+ .owner = THIS_MODULE,
-+ .llseek = no_llseek,
-+ .read = hostaudio_read,
-+ .write = hostaudio_write,
-+ .poll = hostaudio_poll,
-+ .ioctl = hostaudio_ioctl,
-+ .mmap = NULL,
-+ .open = hostaudio_open,
-+ .release = hostaudio_release,
-+};
-+
-+static struct file_operations hostmixer_fops = {
-+ .owner = THIS_MODULE,
-+ .llseek = no_llseek,
-+ .ioctl = hostmixer_ioctl_mixdev,
-+ .open = hostmixer_open_mixdev,
-+ .release = hostmixer_release,
-+};
-+
-+struct {
-+ int dev_audio;
-+ int dev_mixer;
-+} module_data;
-+
-+MODULE_AUTHOR("Steve Schmidtke");
-+MODULE_DESCRIPTION("UML Audio Relay");
-+MODULE_LICENSE("GPL");
-+
-+static int __init hostaudio_init_module(void)
-+{
-+ printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n",
-+ dsp, mixer);
-+
-+ module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1);
-+ if(module_data.dev_audio < 0){
-+ printk(KERN_ERR "hostaudio: couldn't register DSP device!\n");
-+ return -ENODEV;
-+ }
-+
-+ module_data.dev_mixer = register_sound_mixer(&hostmixer_fops, -1);
-+ if(module_data.dev_mixer < 0){
-+ printk(KERN_ERR "hostmixer: couldn't register mixer "
-+ "device!\n");
-+ unregister_sound_dsp(module_data.dev_audio);
-+ return -ENODEV;
-+ }
-+
-+ return 0;
-+}
-+
-+static void __exit hostaudio_cleanup_module (void)
-+{
-+ unregister_sound_mixer(module_data.dev_mixer);
-+ unregister_sound_dsp(module_data.dev_audio);
-+}
-+
-+module_init(hostaudio_init_module);
-+module_exit(hostaudio_cleanup_module);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/line.c um/arch/um/drivers/line.c
---- orig/arch/um/drivers/line.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/line.c 2003-11-07 03:03:57.000000000 -0500
-@@ -0,0 +1,610 @@
-+/*
-+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/sched.h"
-+#include "linux/slab.h"
-+#include "linux/list.h"
-+#include "linux/devfs_fs_kernel.h"
-+#include "asm/irq.h"
-+#include "asm/uaccess.h"
-+#include "chan_kern.h"
-+#include "irq_user.h"
-+#include "line.h"
-+#include "kern.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "os.h"
-+#include "irq_kern.h"
-+
-+#define LINE_BUFSIZE 4096
-+
-+static void line_interrupt(int irq, void *data, struct pt_regs *unused)
-+{
-+ struct line *dev = data;
-+
-+ if(dev->count > 0)
-+ chan_interrupt(&dev->chan_list, &dev->task, dev->tty, irq,
-+ dev);
-+}
-+
-+static void line_timer_cb(void *arg)
-+{
-+ struct line *dev = arg;
-+
-+ line_interrupt(dev->driver->read_irq, dev, NULL);
-+}
-+
-+static int write_room(struct line *dev)
-+{
-+ int n;
-+
-+ if(dev->buffer == NULL) return(LINE_BUFSIZE - 1);
-+
-+ n = dev->head - dev->tail;
-+ if(n <= 0) n = LINE_BUFSIZE + n;
-+ return(n - 1);
-+}
-+
-+static int buffer_data(struct line *line, const char *buf, int len)
-+{
-+ int end, room;
-+
-+ if(line->buffer == NULL){
-+ line->buffer = kmalloc(LINE_BUFSIZE, GFP_ATOMIC);
-+ if(line->buffer == NULL){
-+ printk("buffer_data - atomic allocation failed\n");
-+ return(0);
-+ }
-+ line->head = line->buffer;
-+ line->tail = line->buffer;
-+ }
-+
-+ room = write_room(line);
-+ len = (len > room) ? room : len;
-+
-+ end = line->buffer + LINE_BUFSIZE - line->tail;
-+ if(len < end){
-+ memcpy(line->tail, buf, len);
-+ line->tail += len;
-+ }
-+ else {
-+ memcpy(line->tail, buf, end);
-+ buf += end;
-+ len -= end;
-+ memcpy(line->buffer, buf, len);
-+ line->tail = line->buffer + len;
-+ }
-+
-+ return(len);
-+}
-+
-+static int flush_buffer(struct line *line)
-+{
-+ int n, count;
-+
-+ if((line->buffer == NULL) || (line->head == line->tail)) return(1);
-+
-+ if(line->tail < line->head){
-+ count = line->buffer + LINE_BUFSIZE - line->head;
-+ n = write_chan(&line->chan_list, line->head, count,
-+ line->driver->write_irq);
-+ if(n < 0) return(n);
-+ if(n == count) line->head = line->buffer;
-+ else {
-+ line->head += n;
-+ return(0);
-+ }
-+ }
-+
-+ count = line->tail - line->head;
-+ n = write_chan(&line->chan_list, line->head, count,
-+ line->driver->write_irq);
-+ if(n < 0) return(n);
-+
-+ line->head += n;
-+ return(line->head == line->tail);
-+}
-+
-+int line_write(struct line *lines, struct tty_struct *tty, int from_user,
-+ const char *buf, int len)
-+{
-+ struct line *line;
-+ char *new;
-+ unsigned long flags;
-+ int n, err, i, ret = 0;
-+
-+ if(tty->stopped) return 0;
-+
-+ if(from_user){
-+ new = kmalloc(len, GFP_KERNEL);
-+ if(new == NULL)
-+ return(0);
-+ n = copy_from_user(new, buf, len);
-+ buf = new;
-+ if(n == len){
-+ len = -EFAULT;
-+ goto out_free;
-+ }
-+
-+ len -= n;
-+ }
-+
-+ i = minor(tty->device) - tty->driver.minor_start;
-+ line = &lines[i];
-+
-+ down(&line->sem);
-+ if(line->head != line->tail){
-+ local_irq_save(flags);
-+ ret += buffer_data(line, buf, len);
-+ err = flush_buffer(line);
-+ local_irq_restore(flags);
-+ if(err <= 0)
-+ goto out_up;
-+ }
-+ else {
-+ n = write_chan(&line->chan_list, buf, len,
-+ line->driver->write_irq);
-+ if(n < 0){
-+ ret = n;
-+ goto out_up;
-+ }
-+
-+ len -= n;
-+ ret += n;
-+ if(len > 0)
-+ ret += buffer_data(line, buf + n, len);
-+ }
-+ out_up:
-+ up(&line->sem);
-+
-+ out_free:
-+ if(from_user)
-+ kfree(buf);
-+ return(ret);
-+}
-+
-+static void line_write_interrupt(int irq, void *data, struct pt_regs *unused)
-+{
-+ struct line *dev = data;
-+ struct tty_struct *tty = dev->tty;
-+ int err;
-+
-+ err = flush_buffer(dev);
-+ if(err == 0) return;
-+ else if(err < 0){
-+ dev->head = dev->buffer;
-+ dev->tail = dev->buffer;
-+ }
-+
-+ if(tty == NULL) return;
-+
-+ if(test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
-+ (tty->ldisc.write_wakeup != NULL))
-+ (tty->ldisc.write_wakeup)(tty);
-+
-+ /* BLOCKING mode
-+ * In blocking mode, everything sleeps on tty->write_wait.
-+ * Sleeping in the console driver would break non-blocking
-+ * writes.
-+ */
-+
-+ if (waitqueue_active(&tty->write_wait))
-+ wake_up_interruptible(&tty->write_wait);
-+
-+}
-+
-+int line_setup_irq(int fd, int input, int output, void *data)
-+{
-+ struct line *line = data;
-+ struct line_driver *driver = line->driver;
-+ int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM;
-+
-+ if(input) err = um_request_irq(driver->read_irq, fd, IRQ_READ,
-+ line_interrupt, flags,
-+ driver->read_irq_name, line);
-+ if(err) return(err);
-+ if(output) err = um_request_irq(driver->write_irq, fd, IRQ_WRITE,
-+ line_write_interrupt, flags,
-+ driver->write_irq_name, line);
-+ line->have_irq = 1;
-+ return(err);
-+}
-+
-+void line_disable(struct line *line, int current_irq)
-+{
-+ if(!line->have_irq) return;
-+
-+ if(line->driver->read_irq == current_irq)
-+ free_irq_later(line->driver->read_irq, line);
-+ else
-+ free_irq(line->driver->read_irq, line);
-+
-+ if(line->driver->write_irq == current_irq)
-+ free_irq_later(line->driver->write_irq, line);
-+ else
-+ free_irq(line->driver->write_irq, line);
-+
-+ line->have_irq = 0;
-+}
-+
-+int line_open(struct line *lines, struct tty_struct *tty,
-+ struct chan_opts *opts)
-+{
-+ struct line *line;
-+ int n, err = 0;
-+
-+ if(tty == NULL) n = 0;
-+ else n = minor(tty->device) - tty->driver.minor_start;
-+ line = &lines[n];
-+
-+ down(&line->sem);
-+ if(line->count == 0){
-+ if(!line->valid){
-+ err = -ENODEV;
-+ goto out;
-+ }
-+ if(list_empty(&line->chan_list)){
-+ err = parse_chan_pair(line->init_str, &line->chan_list,
-+ line->init_pri, n, opts);
-+ if(err) goto out;
-+ err = open_chan(&line->chan_list);
-+ if(err) goto out;
-+ }
-+ enable_chan(&line->chan_list, line);
-+ INIT_TQUEUE(&line->task, line_timer_cb, line);
-+ }
-+
-+ if(!line->sigio){
-+ chan_enable_winch(&line->chan_list, line);
-+ line->sigio = 1;
-+ }
-+
-+ /* This is outside the if because the initial console is opened
-+ * with tty == NULL
-+ */
-+ line->tty = tty;
-+
-+ if(tty != NULL){
-+ tty->driver_data = line;
-+ chan_window_size(&line->chan_list, &tty->winsize.ws_row,
-+ &tty->winsize.ws_col);
-+ }
-+
-+ line->count++;
-+ out:
-+ up(&line->sem);
-+ return(err);
-+}
-+
-+void line_close(struct line *lines, struct tty_struct *tty)
-+{
-+ struct line *line;
-+ int n;
-+
-+ if(tty == NULL) n = 0;
-+ else n = minor(tty->device) - tty->driver.minor_start;
-+ line = &lines[n];
-+
-+ down(&line->sem);
-+ line->count--;
-+
-+ /* I don't like this, but I can't think of anything better. What's
-+ * going on is that the tty is in the process of being closed for
-+ * the last time. Its count hasn't been dropped yet, so it's still
-+ * at 1. This may happen when line->count != 0 because of the initial
-+ * console open (without a tty) bumping it up to 1.
-+ */
-+ if((line->tty != NULL) && (line->tty->count == 1))
-+ line->tty = NULL;
-+ if(line->count == 0)
-+ line_disable(line, -1);
-+ up(&line->sem);
-+}
-+
-+void close_lines(struct line *lines, int nlines)
-+{
-+ int i;
-+
-+ for(i = 0; i < nlines; i++)
-+ close_chan(&lines[i].chan_list);
-+}
-+
-+int line_setup(struct line *lines, int num, char *init, int all_allowed)
-+{
-+ int i, n;
-+ char *end;
-+
-+ if(*init == '=') n = -1;
-+ else {
-+ n = simple_strtoul(init, &end, 0);
-+ if(*end != '='){
-+ printk(KERN_ERR "line_setup failed to parse \"%s\"\n",
-+ init);
-+ return(0);
-+ }
-+ init = end;
-+ }
-+ init++;
-+ if((n >= 0) && (n >= num)){
-+ printk("line_setup - %d out of range ((0 ... %d) allowed)\n",
-+ n, num);
-+ return(0);
-+ }
-+ else if(n >= 0){
-+ if(lines[n].count > 0){
-+ printk("line_setup - device %d is open\n", n);
-+ return(0);
-+ }
-+ if(lines[n].init_pri <= INIT_ONE){
-+ lines[n].init_pri = INIT_ONE;
-+ if(!strcmp(init, "none")) lines[n].valid = 0;
-+ else {
-+ lines[n].init_str = init;
-+ lines[n].valid = 1;
-+ }
-+ }
-+ }
-+ else if(!all_allowed){
-+ printk("line_setup - can't configure all devices from "
-+ "mconsole\n");
-+ return(0);
-+ }
-+ else {
-+ for(i = 0; i < num; i++){
-+ if(lines[i].init_pri <= INIT_ALL){
-+ lines[i].init_pri = INIT_ALL;
-+ if(!strcmp(init, "none")) lines[i].valid = 0;
-+ else {
-+ lines[i].init_str = init;
-+ lines[i].valid = 1;
-+ }
-+ }
-+ }
-+ }
-+ return(1);
-+}
-+
-+int line_config(struct line *lines, int num, char *str)
-+{
-+ char *new = uml_strdup(str);
-+
-+ if(new == NULL){
-+ printk("line_config - uml_strdup failed\n");
-+ return(-ENOMEM);
-+ }
-+ return(!line_setup(lines, num, new, 0));
-+}
-+
-+int line_get_config(char *name, struct line *lines, int num, char *str,
-+ int size, char **error_out)
-+{
-+ struct line *line;
-+ char *end;
-+ int dev, n = 0;
-+
-+ dev = simple_strtoul(name, &end, 0);
-+ if((*end != '\0') || (end == name)){
-+ *error_out = "line_get_config failed to parse device number";
-+ return(0);
-+ }
-+
-+ if((dev < 0) || (dev >= num)){
-+ *error_out = "device number of of range";
-+ return(0);
-+ }
-+
-+ line = &lines[dev];
-+
-+ down(&line->sem);
-+ if(!line->valid)
-+ CONFIG_CHUNK(str, size, n, "none", 1);
-+ else if(line->count == 0)
-+ CONFIG_CHUNK(str, size, n, line->init_str, 1);
-+ else n = chan_config_string(&line->chan_list, str, size, error_out);
-+ up(&line->sem);
-+
-+ return(n);
-+}
-+
-+int line_remove(struct line *lines, int num, char *str)
-+{
-+ char config[sizeof("conxxxx=none\0")];
-+
-+ sprintf(config, "%s=none", str);
-+ return(!line_setup(lines, num, config, 0));
-+}
-+
-+static int line_write_room(struct tty_struct *tty)
-+{
-+ struct line *dev = tty->driver_data;
-+
-+ return(write_room(dev));
-+}
-+
-+void line_register_devfs(struct lines *set, struct line_driver *line_driver,
-+ struct tty_driver *driver, struct line *lines,
-+ int nlines)
-+{
-+ int err, i, n;
-+ char *from, *to;
-+
-+ driver->driver_name = line_driver->name;
-+ driver->name = line_driver->devfs_name;
-+ driver->major = line_driver->major;
-+ driver->minor_start = line_driver->minor_start;
-+ driver->type = line_driver->type;
-+ driver->subtype = line_driver->subtype;
-+ driver->magic = TTY_DRIVER_MAGIC;
-+ driver->flags = TTY_DRIVER_REAL_RAW;
-+
-+ n = set->num;
-+ driver->num = n;
-+ driver->table = kmalloc(n * sizeof(driver->table[0]), GFP_KERNEL);
-+ driver->termios = kmalloc(n * sizeof(driver->termios[0]), GFP_KERNEL);
-+ driver->termios_locked = kmalloc(n * sizeof(driver->termios_locked[0]),
-+ GFP_KERNEL);
-+ if((driver->table == NULL) || (driver->termios == NULL) ||
-+ (driver->termios_locked == NULL))
-+ panic("Failed to allocate driver table");
-+
-+ memset(driver->table, 0, n * sizeof(driver->table[0]));
-+ memset(driver->termios, 0, n * sizeof(driver->termios[0]));
-+ memset(driver->termios_locked, 0,
-+ n * sizeof(driver->termios_locked[0]));
-+
-+ driver->write_room = line_write_room;
-+ driver->init_termios = tty_std_termios;
-+
-+ if (tty_register_driver(driver))
-+ panic("line_register_devfs : Couldn't register driver\n");
-+
-+ from = line_driver->symlink_from;
-+ to = line_driver->symlink_to;
-+ err = devfs_mk_symlink(NULL, from, 0, to, NULL, NULL);
-+ if(err) printk("Symlink creation from /dev/%s to /dev/%s "
-+ "returned %d\n", from, to, err);
-+
-+ for(i = 0; i < nlines; i++){
-+ if(!lines[i].valid)
-+ tty_unregister_devfs(driver, driver->minor_start + i);
-+ }
-+
-+ mconsole_register_dev(&line_driver->mc);
-+}
-+
-+void lines_init(struct line *lines, int nlines)
-+{
-+ struct line *line;
-+ int i;
-+
-+ for(i = 0; i < nlines; i++){
-+ line = &lines[i];
-+ INIT_LIST_HEAD(&line->chan_list);
-+ sema_init(&line->sem, 1);
-+ if(line->init_str != NULL){
-+ line->init_str = uml_strdup(line->init_str);
-+ if(line->init_str == NULL)
-+ printk("lines_init - uml_strdup returned "
-+ "NULL\n");
-+ }
-+ }
-+}
-+
-+struct winch {
-+ struct list_head list;
-+ int fd;
-+ int tty_fd;
-+ int pid;
-+ struct line *line;
-+};
-+
-+void winch_interrupt(int irq, void *data, struct pt_regs *unused)
-+{
-+ struct winch *winch = data;
-+ struct tty_struct *tty;
-+ int err;
-+ char c;
-+
-+ if(winch->fd != -1){
-+ err = generic_read(winch->fd, &c, NULL);
-+ if(err < 0){
-+ if(err != -EAGAIN){
-+ printk("winch_interrupt : read failed, "
-+ "errno = %d\n", -err);
-+ printk("fd %d is losing SIGWINCH support\n",
-+ winch->tty_fd);
-+ return;
-+ }
-+ goto out;
-+ }
-+ }
-+ tty = winch->line->tty;
-+ if(tty != NULL){
-+ chan_window_size(&winch->line->chan_list,
-+ &tty->winsize.ws_row,
-+ &tty->winsize.ws_col);
-+ kill_pg(tty->pgrp, SIGWINCH, 1);
-+ }
-+ out:
-+ if(winch->fd != -1)
-+ reactivate_fd(winch->fd, WINCH_IRQ);
-+}
-+
-+DECLARE_MUTEX(winch_handler_sem);
-+LIST_HEAD(winch_handlers);
-+
-+void register_winch_irq(int fd, int tty_fd, int pid, void *line)
-+{
-+ struct winch *winch;
-+
-+ down(&winch_handler_sem);
-+ winch = kmalloc(sizeof(*winch), GFP_KERNEL);
-+ if(winch == NULL){
-+ printk("register_winch_irq - kmalloc failed\n");
-+ goto out;
-+ }
-+ *winch = ((struct winch) { .list = LIST_HEAD_INIT(winch->list),
-+ .fd = fd,
-+ .tty_fd = tty_fd,
-+ .pid = pid,
-+ .line = line });
-+ list_add(&winch->list, &winch_handlers);
-+ if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
-+ SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
-+ "winch", winch) < 0)
-+ printk("register_winch_irq - failed to register IRQ\n");
-+ out:
-+ up(&winch_handler_sem);
-+}
-+
-+static void winch_cleanup(void)
-+{
-+ struct list_head *ele;
-+ struct winch *winch;
-+
-+ list_for_each(ele, &winch_handlers){
-+ winch = list_entry(ele, struct winch, list);
-+ if(winch->fd != -1){
-+ deactivate_fd(winch->fd, WINCH_IRQ);
-+ os_close_file(winch->fd);
-+ }
-+ if(winch->pid != -1)
-+ os_kill_process(winch->pid, 1);
-+ }
-+}
-+
-+__uml_exitcall(winch_cleanup);
-+
-+char *add_xterm_umid(char *base)
-+{
-+ char *umid, *title;
-+ int len;
-+
-+ umid = get_umid(1);
-+ if(umid == NULL) return(base);
-+
-+ len = strlen(base) + strlen(" ()") + strlen(umid) + 1;
-+ title = kmalloc(len, GFP_KERNEL);
-+ if(title == NULL){
-+ printk("Failed to allocate buffer for xterm title\n");
-+ return(base);
-+ }
-+
-+ strncpy(title, base, len);
-+ len -= strlen(title);
-+ snprintf(&title[strlen(title)], len, " (%s)", umid);
-+ return(title);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/Makefile um/arch/um/drivers/Makefile
---- orig/arch/um/drivers/Makefile 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/Makefile 2004-02-12 03:55:08.000000000 -0500
-@@ -0,0 +1,97 @@
-+#
-+# Copyright (C) 2000, 2002, 2003 Jeff Dike (jdike@karaya.com)
-+# Licensed under the GPL
-+#
-+
-+O_TARGET := built-in.o
-+
-+CHAN_OBJS := chan_kern.o chan_user.o line.o
-+
-+list-multi := slip.o slirp.o daemon.o mcast.o mconsole.o net.o ubd.o \
-+ hostaudio.o pcap.o port.o harddog.o
-+
-+slip-objs := slip_kern.o slip_user.o
-+slirp-objs := slirp_kern.o slirp_user.o
-+daemon-objs := daemon_kern.o daemon_user.o
-+mcast-objs := mcast_kern.o mcast_user.o
-+pcap-objs := pcap_kern.o pcap_user.o
-+pcap-libs := -lpcap -L/usr/lib
-+net-objs := net_kern.o net_user.o
-+mconsole-objs := mconsole_kern.o mconsole_user.o
-+hostaudio-objs := hostaudio_kern.o
-+ubd-objs := ubd_kern.o ubd_user.o
-+port-objs := port_kern.o port_user.o
-+harddog-objs := harddog_kern.o harddog_user.o
-+
-+export-objs := mconsole_kern.o
-+
-+obj-y =
-+obj-$(CONFIG_SSL) += ssl.o
-+obj-$(CONFIG_UML_NET_SLIP) += slip.o
-+obj-$(CONFIG_UML_NET_SLIRP) += slirp.o
-+obj-$(CONFIG_UML_NET_DAEMON) += daemon.o
-+obj-$(CONFIG_UML_NET_MCAST) += mcast.o
-+obj-$(CONFIG_UML_NET_PCAP) += pcap.o
-+obj-$(CONFIG_UML_NET) += net.o
-+obj-$(CONFIG_MCONSOLE) += mconsole.o
-+obj-$(CONFIG_MMAPPER) += mmapper_kern.o
-+obj-$(CONFIG_BLK_DEV_UBD) += ubd.o
-+obj-$(CONFIG_HOSTAUDIO) += hostaudio.o
-+obj-$(CONFIG_FD_CHAN) += fd.o
-+obj-$(CONFIG_NULL_CHAN) += null.o
-+obj-$(CONFIG_PORT_CHAN) += port.o
-+obj-$(CONFIG_PTY_CHAN) += pty.o
-+obj-$(CONFIG_TTY_CHAN) += tty.o
-+obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o
-+obj-$(CONFIG_UML_WATCHDOG) += harddog.o
-+obj-$(CONFIG_COW) += cow_kern.o
-+obj-$(CONFIG_COW_COMMON) += cow_user.o
-+
-+CFLAGS_pcap_user.o = -I/usr/include/pcap
-+
-+obj-y += stdio_console.o $(CHAN_OBJS)
-+
-+USER_SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs))
-+
-+USER_OBJS = $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) fd.o \
-+ null.o pty.o tty.o xterm.o
-+
-+include $(TOPDIR)/Rules.make
-+
-+$(USER_OBJS) : %.o: %.c
-+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $<
-+
-+clean:
-+
-+modules:
-+
-+fastdep:
-+
-+dep:
-+
-+archmrproper:
-+
-+daemon.o : $(daemon-objs)
-+
-+slip.o : $(slip-objs)
-+
-+slirp.o : $(slirp-objs)
-+
-+mcast.o : $(mcast-objs)
-+
-+pcap.o : $(pcap-objs)
-+
-+mconsole.o : $(mconsole-objs)
-+
-+net.o : $(net-objs)
-+
-+hostaudio.o : $(hostaudio-objs)
-+
-+ubd.o : $(ubd-objs)
-+
-+port.o : $(port-objs)
-+
-+harddog.o : $(harddog-objs)
-+
-+$(list-multi) : # This doesn't work, but should : '%.o : $(%-objs)'
-+ $(LD) -r -o $@ $($(patsubst %.o,%,$@)-objs) $($(patsubst %.o,%,$@)-libs)
-diff -Naur -X ../exclude-files orig/arch/um/drivers/mcast.h um/arch/um/drivers/mcast.h
---- orig/arch/um/drivers/mcast.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/mcast.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,30 @@
-+/*
-+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "net_user.h"
-+
-+struct mcast_data {
-+ char *addr;
-+ unsigned short port;
-+ void *mcast_addr;
-+ int ttl;
-+ void *dev;
-+};
-+
-+extern struct net_user_info mcast_user_info;
-+
-+extern int mcast_user_write(int fd, void *buf, int len,
-+ struct mcast_data *pri);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/mcast_kern.c um/arch/um/drivers/mcast_kern.c
---- orig/arch/um/drivers/mcast_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/mcast_kern.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,145 @@
-+/*
-+ * user-mode-linux networking multicast transport
-+ * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org>
-+ *
-+ * based on the existing uml-networking code, which is
-+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
-+ * James Leu (jleu@mindspring.net).
-+ * Copyright (C) 2001 by various other people who didn't put their name here.
-+ *
-+ * Licensed under the GPL.
-+ */
-+
-+#include "linux/kernel.h"
-+#include "linux/init.h"
-+#include "linux/netdevice.h"
-+#include "linux/etherdevice.h"
-+#include "linux/in.h"
-+#include "linux/inet.h"
-+#include "net_kern.h"
-+#include "net_user.h"
-+#include "mcast.h"
-+
-+struct mcast_init {
-+ char *addr;
-+ int port;
-+ int ttl;
-+};
-+
-+void mcast_init(struct net_device *dev, void *data)
-+{
-+ struct uml_net_private *pri;
-+ struct mcast_data *dpri;
-+ struct mcast_init *init = data;
-+
-+ init_etherdev(dev, 0);
-+ pri = dev->priv;
-+ dpri = (struct mcast_data *) pri->user;
-+ *dpri = ((struct mcast_data)
-+ { .addr = init->addr,
-+ .port = init->port,
-+ .ttl = init->ttl,
-+ .mcast_addr = NULL,
-+ .dev = dev });
-+ printk("mcast backend ");
-+ printk("multicast adddress: %s:%u, TTL:%u ",
-+ dpri->addr, dpri->port, dpri->ttl);
-+
-+ printk("\n");
-+}
-+
-+static int mcast_read(int fd, struct sk_buff **skb, struct uml_net_private *lp)
-+{
-+ *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER);
-+ if(*skb == NULL) return(-ENOMEM);
-+ return(net_recvfrom(fd, (*skb)->mac.raw,
-+ (*skb)->dev->mtu + ETH_HEADER_OTHER));
-+}
-+
-+static int mcast_write(int fd, struct sk_buff **skb,
-+ struct uml_net_private *lp)
-+{
-+ return mcast_user_write(fd, (*skb)->data, (*skb)->len,
-+ (struct mcast_data *) &lp->user);
-+}
-+
-+static struct net_kern_info mcast_kern_info = {
-+ .init = mcast_init,
-+ .protocol = eth_protocol,
-+ .read = mcast_read,
-+ .write = mcast_write,
-+};
-+
-+int mcast_setup(char *str, char **mac_out, void *data)
-+{
-+ struct mcast_init *init = data;
-+ char *port_str = NULL, *ttl_str = NULL, *remain;
-+ char *last;
-+ int n;
-+
-+ *init = ((struct mcast_init)
-+ { .addr = "239.192.168.1",
-+ .port = 1102,
-+ .ttl = 1 });
-+
-+ remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str,
-+ NULL);
-+ if(remain != NULL){
-+ printk(KERN_ERR "mcast_setup - Extra garbage on "
-+ "specification : '%s'\n", remain);
-+ return(0);
-+ }
-+
-+ if(port_str != NULL){
-+ n = simple_strtoul(port_str, &last, 10);
-+ if((*last != '\0') || (last == port_str)){
-+ printk(KERN_ERR "mcast_setup - Bad port : '%s'\n",
-+ port_str);
-+ return(0);
-+ }
-+ init->port = htons(n);
-+ }
-+
-+ if(ttl_str != NULL){
-+ init->ttl = simple_strtoul(ttl_str, &last, 10);
-+ if((*last != '\0') || (last == ttl_str)){
-+ printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n",
-+ ttl_str);
-+ return(0);
-+ }
-+ }
-+
-+ printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr,
-+ init->port, init->ttl);
-+
-+ return(1);
-+}
-+
-+static struct transport mcast_transport = {
-+ .list = LIST_HEAD_INIT(mcast_transport.list),
-+ .name = "mcast",
-+ .setup = mcast_setup,
-+ .user = &mcast_user_info,
-+ .kern = &mcast_kern_info,
-+ .private_size = sizeof(struct mcast_data),
-+ .setup_size = sizeof(struct mcast_init),
-+};
-+
-+static int register_mcast(void)
-+{
-+ register_transport(&mcast_transport);
-+ return(1);
-+}
-+
-+__initcall(register_mcast);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/mcast_user.c um/arch/um/drivers/mcast_user.c
---- orig/arch/um/drivers/mcast_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/mcast_user.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,177 @@
-+/*
-+ * user-mode-linux networking multicast transport
-+ * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org>
-+ *
-+ * based on the existing uml-networking code, which is
-+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
-+ * James Leu (jleu@mindspring.net).
-+ * Copyright (C) 2001 by various other people who didn't put their name here.
-+ *
-+ * Licensed under the GPL.
-+ *
-+ */
-+
-+#include <errno.h>
-+#include <unistd.h>
-+#include <linux/inet.h>
-+#include <sys/socket.h>
-+#include <sys/un.h>
-+#include <sys/time.h>
-+#include <netinet/in.h>
-+#include "net_user.h"
-+#include "mcast.h"
-+#include "kern_util.h"
-+#include "user_util.h"
-+#include "user.h"
-+#include "os.h"
-+
-+#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
-+
-+static struct sockaddr_in *new_addr(char *addr, unsigned short port)
-+{
-+ struct sockaddr_in *sin;
-+
-+ sin = um_kmalloc(sizeof(struct sockaddr_in));
-+ if(sin == NULL){
-+ printk("new_addr: allocation of sockaddr_in failed\n");
-+ return(NULL);
-+ }
-+ sin->sin_family = AF_INET;
-+ sin->sin_addr.s_addr = in_aton(addr);
-+ sin->sin_port = port;
-+ return(sin);
-+}
-+
-+static void mcast_user_init(void *data, void *dev)
-+{
-+ struct mcast_data *pri = data;
-+
-+ pri->mcast_addr = new_addr(pri->addr, pri->port);
-+ pri->dev = dev;
-+}
-+
-+static int mcast_open(void *data)
-+{
-+ struct mcast_data *pri = data;
-+ struct sockaddr_in *sin = pri->mcast_addr;
-+ struct ip_mreq mreq;
-+ int fd, yes = 1;
-+
-+
-+ if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) {
-+ fd = -EINVAL;
-+ goto out;
-+ }
-+
-+ fd = socket(AF_INET, SOCK_DGRAM, 0);
-+ if (fd < 0){
-+ printk("mcast_open : data socket failed, errno = %d\n",
-+ errno);
-+ fd = -ENOMEM;
-+ goto out;
-+ }
-+
-+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
-+ printk("mcast_open: SO_REUSEADDR failed, errno = %d\n",
-+ errno);
-+ os_close_file(fd);
-+ fd = -EINVAL;
-+ goto out;
-+ }
-+
-+ /* set ttl according to config */
-+ if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl,
-+ sizeof(pri->ttl)) < 0) {
-+ printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n",
-+ errno);
-+ os_close_file(fd);
-+ fd = -EINVAL;
-+ goto out;
-+ }
-+
-+ /* set LOOP, so data does get fed back to local sockets */
-+ if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
-+ printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n",
-+ errno);
-+ os_close_file(fd);
-+ fd = -EINVAL;
-+ goto out;
-+ }
-+
-+ /* bind socket to mcast address */
-+ if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) {
-+ printk("mcast_open : data bind failed, errno = %d\n", errno);
-+ os_close_file(fd);
-+ fd = -EINVAL;
-+ goto out;
-+ }
-+
-+ /* subscribe to the multicast group */
-+ mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr;
-+ mreq.imr_interface.s_addr = 0;
-+ if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP,
-+ &mreq, sizeof(mreq)) < 0) {
-+ printk("mcast_open: IP_ADD_MEMBERSHIP failed, error = %d\n",
-+ errno);
-+ printk("There appears not to be a multicast-capable network "
-+ "interface on the host.\n");
-+ printk("eth0 should be configured in order to use the "
-+ "multicast transport.\n");
-+ os_close_file(fd);
-+ fd = -EINVAL;
-+ }
-+
-+ out:
-+ return(fd);
-+}
-+
-+static void mcast_close(int fd, void *data)
-+{
-+ struct ip_mreq mreq;
-+ struct mcast_data *pri = data;
-+ struct sockaddr_in *sin = pri->mcast_addr;
-+
-+ mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr;
-+ mreq.imr_interface.s_addr = 0;
-+ if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP,
-+ &mreq, sizeof(mreq)) < 0) {
-+ printk("mcast_open: IP_DROP_MEMBERSHIP failed, error = %d\n",
-+ errno);
-+ }
-+
-+ os_close_file(fd);
-+}
-+
-+int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri)
-+{
-+ struct sockaddr_in *data_addr = pri->mcast_addr;
-+
-+ return(net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)));
-+}
-+
-+static int mcast_set_mtu(int mtu, void *data)
-+{
-+ return(mtu);
-+}
-+
-+struct net_user_info mcast_user_info = {
-+ .init = mcast_user_init,
-+ .open = mcast_open,
-+ .close = mcast_close,
-+ .remove = NULL,
-+ .set_mtu = mcast_set_mtu,
-+ .add_address = NULL,
-+ .delete_address = NULL,
-+ .max_packet = MAX_PACKET - ETH_HEADER_OTHER
-+};
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/mconsole_kern.c um/arch/um/drivers/mconsole_kern.c
---- orig/arch/um/drivers/mconsole_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/mconsole_kern.c 2004-02-12 03:09:12.000000000 -0500
-@@ -0,0 +1,560 @@
-+/*
-+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
-+ * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/kernel.h"
-+#include "linux/slab.h"
-+#include "linux/init.h"
-+#include "linux/notifier.h"
-+#include "linux/reboot.h"
-+#include "linux/utsname.h"
-+#include "linux/ctype.h"
-+#include "linux/interrupt.h"
-+#include "linux/sysrq.h"
-+#include "linux/tqueue.h"
-+#include "linux/module.h"
-+#include "linux/file.h"
-+#include "linux/fs.h"
-+#include "linux/proc_fs.h"
-+#include "asm/irq.h"
-+#include "asm/uaccess.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "kern.h"
-+#include "mconsole.h"
-+#include "mconsole_kern.h"
-+#include "irq_user.h"
-+#include "init.h"
-+#include "os.h"
-+#include "umid.h"
-+#include "irq_kern.h"
-+
-+static int do_unlink_socket(struct notifier_block *notifier,
-+ unsigned long what, void *data)
-+{
-+ return(mconsole_unlink_socket());
-+}
-+
-+
-+static struct notifier_block reboot_notifier = {
-+ .notifier_call = do_unlink_socket,
-+ .priority = 0,
-+};
-+
-+/* Safe without explicit locking for now. Tasklets provide their own
-+ * locking, and the interrupt handler is safe because it can't interrupt
-+ * itself and it can only happen on CPU 0.
-+ */
-+
-+LIST_HEAD(mc_requests);
-+
-+void mc_task_proc(void *unused)
-+{
-+ struct mconsole_entry *req;
-+ unsigned long flags;
-+ int done;
-+
-+ do {
-+ save_flags(flags);
-+ req = list_entry(mc_requests.next, struct mconsole_entry,
-+ list);
-+ list_del(&req->list);
-+ done = list_empty(&mc_requests);
-+ restore_flags(flags);
-+ req->request.cmd->handler(&req->request);
-+ kfree(req);
-+ } while(!done);
-+}
-+
-+struct tq_struct mconsole_task = {
-+ .routine = mc_task_proc,
-+ .data = NULL
-+};
-+
-+void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ int fd;
-+ struct mconsole_entry *new;
-+ struct mc_request req;
-+
-+ fd = (int) dev_id;
-+ while (mconsole_get_request(fd, &req)){
-+ if(req.cmd->context == MCONSOLE_INTR)
-+ (*req.cmd->handler)(&req);
-+ else {
-+ new = kmalloc(sizeof(*new), GFP_ATOMIC);
-+ if(new == NULL)
-+ mconsole_reply(&req, "Out of memory", 1, 0);
-+ else {
-+ new->request = req;
-+ list_add(&new->list, &mc_requests);
-+ }
-+ }
-+ }
-+ if(!list_empty(&mc_requests)) schedule_task(&mconsole_task);
-+ reactivate_fd(fd, MCONSOLE_IRQ);
-+}
-+
-+void mconsole_version(struct mc_request *req)
-+{
-+ char version[256];
-+
-+ sprintf(version, "%s %s %s %s %s", system_utsname.sysname,
-+ system_utsname.nodename, system_utsname.release,
-+ system_utsname.version, system_utsname.machine);
-+ mconsole_reply(req, version, 0, 0);
-+}
-+
-+void mconsole_log(struct mc_request *req)
-+{
-+ int len;
-+ char *ptr = req->request.data;
-+
-+ ptr += strlen("log ");
-+
-+ len = req->len - (ptr - req->request.data);
-+ printk("%.*s", len, ptr);
-+ mconsole_reply(req, "", 0, 0);
-+}
-+
-+void mconsole_proc(struct mc_request *req)
-+{
-+ struct nameidata nd;
-+ struct file_system_type *proc;
-+ struct super_block *super;
-+ struct file *file;
-+ int n, err;
-+ char *ptr = req->request.data, *buf;
-+
-+ ptr += strlen("proc");
-+ while(isspace(*ptr)) ptr++;
-+
-+ proc = get_fs_type("proc");
-+ if(proc == NULL){
-+ mconsole_reply(req, "procfs not registered", 1, 0);
-+ goto out;
-+ }
-+
-+ super = get_anon_super(proc, NULL, NULL);
-+ if(super == NULL){
-+ mconsole_reply(req, "Failed to get procfs superblock", 1, 0);
-+ goto out_put;
-+ }
-+
-+ if(super->s_root == NULL){
-+ super = (*proc->read_super)(super, NULL, 0);
-+ if(super == NULL){
-+ mconsole_reply(req, "Failed to read superblock", 1, 0);
-+ goto out_put;
-+ }
-+ }
-+ up_write(&super->s_umount);
-+
-+ nd.dentry = super->s_root;
-+ nd.mnt = NULL;
-+ nd.flags = O_RDONLY + 1;
-+ nd.last_type = LAST_ROOT;
-+
-+ err = link_path_walk(ptr, &nd);
-+ if(err){
-+ mconsole_reply(req, "Failed to look up file", 1, 0);
-+ goto out_kill;
-+ }
-+
-+ file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
-+ if(IS_ERR(file)){
-+ mconsole_reply(req, "Failed to open file", 1, 0);
-+ goto out_kill;
-+ }
-+
-+ buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
-+ if(buf == NULL){
-+ mconsole_reply(req, "Failed to allocate buffer", 1, 0);
-+ goto out_fput;
-+ }
-+
-+ if((file->f_op != NULL) && (file->f_op->read != NULL)){
-+ do {
-+ n = (*file->f_op->read)(file, buf, PAGE_SIZE - 1,
-+ &file->f_pos);
-+ if(n >= 0){
-+ buf[n] = '\0';
-+ mconsole_reply(req, buf, 0, (n > 0));
-+ }
-+ else {
-+ mconsole_reply(req, "Read of file failed",
-+ 1, 0);
-+ goto out_free;
-+ }
-+ } while(n > 0);
-+ }
-+ else mconsole_reply(req, "", 0, 0);
-+
-+ out_free:
-+ kfree(buf);
-+ out_fput:
-+ fput(file);
-+ out_kill:
-+ kill_super(super);
-+ out_put:
-+ /* put_filesystem(proc); */
-+ out: ;
-+}
-+
-+#define UML_MCONSOLE_HELPTEXT \
-+"Commands: \n\
-+ version - Get kernel version \n\
-+ help - Print this message \n\
-+ halt - Halt UML \n\
-+ reboot - Reboot UML \n\
-+ config <dev>=<config> - Add a new device to UML; \n\
-+ same syntax as command line \n\
-+ config <dev> - Query the configuration of a device \n\
-+ remove <dev> - Remove a device from UML \n\
-+ sysrq <letter> - Performs the SysRq action controlled by the letter \n\
-+ cad - invoke the Ctl-Alt-Del handler \n\
-+ stop - pause the UML; it will do nothing until it receives a 'go' \n\
-+ go - continue the UML after a 'stop' \n\
-+ log <string> - make UML enter <string> into the kernel log\n\
-+ proc <file> - returns the contents of the UML's /proc/<file>\n\
-+"
-+
-+void mconsole_help(struct mc_request *req)
-+{
-+ mconsole_reply(req, UML_MCONSOLE_HELPTEXT, 0, 0);
-+}
-+
-+void mconsole_halt(struct mc_request *req)
-+{
-+ mconsole_reply(req, "", 0, 0);
-+ machine_halt();
-+}
-+
-+void mconsole_reboot(struct mc_request *req)
-+{
-+ mconsole_reply(req, "", 0, 0);
-+ machine_restart(NULL);
-+}
-+
-+extern void ctrl_alt_del(void);
-+
-+void mconsole_cad(struct mc_request *req)
-+{
-+ mconsole_reply(req, "", 0, 0);
-+ ctrl_alt_del();
-+}
-+
-+void mconsole_go(struct mc_request *req)
-+{
-+ mconsole_reply(req, "Not stopped", 1, 0);
-+}
-+
-+void mconsole_stop(struct mc_request *req)
-+{
-+ deactivate_fd(req->originating_fd, MCONSOLE_IRQ);
-+ os_set_fd_block(req->originating_fd, 1);
-+ mconsole_reply(req, "", 0, 0);
-+ while(mconsole_get_request(req->originating_fd, req)){
-+ if(req->cmd->handler == mconsole_go) break;
-+ (*req->cmd->handler)(req);
-+ }
-+ os_set_fd_block(req->originating_fd, 0);
-+ reactivate_fd(req->originating_fd, MCONSOLE_IRQ);
-+ mconsole_reply(req, "", 0, 0);
-+}
-+
-+/* This list is populated by __initcall routines. */
-+
-+LIST_HEAD(mconsole_devices);
-+
-+void mconsole_register_dev(struct mc_device *new)
-+{
-+ list_add(&new->list, &mconsole_devices);
-+}
-+
-+static struct mc_device *mconsole_find_dev(char *name)
-+{
-+ struct list_head *ele;
-+ struct mc_device *dev;
-+
-+ list_for_each(ele, &mconsole_devices){
-+ dev = list_entry(ele, struct mc_device, list);
-+ if(!strncmp(name, dev->name, strlen(dev->name)))
-+ return(dev);
-+ }
-+ return(NULL);
-+}
-+
-+#define CONFIG_BUF_SIZE 64
-+
-+static void mconsole_get_config(int (*get_config)(char *, char *, int,
-+ char **),
-+ struct mc_request *req, char *name)
-+{
-+ char default_buf[CONFIG_BUF_SIZE], *error, *buf;
-+ int n, size;
-+
-+ if(get_config == NULL){
-+ mconsole_reply(req, "No get_config routine defined", 1, 0);
-+ return;
-+ }
-+
-+ error = NULL;
-+ size = sizeof(default_buf)/sizeof(default_buf[0]);
-+ buf = default_buf;
-+
-+ while(1){
-+ n = (*get_config)(name, buf, size, &error);
-+ if(error != NULL){
-+ mconsole_reply(req, error, 1, 0);
-+ goto out;
-+ }
-+
-+ if(n <= size){
-+ mconsole_reply(req, buf, 0, 0);
-+ goto out;
-+ }
-+
-+ if(buf != default_buf)
-+ kfree(buf);
-+
-+ size = n;
-+ buf = kmalloc(size, GFP_KERNEL);
-+ if(buf == NULL){
-+ mconsole_reply(req, "Failed to allocate buffer", 1, 0);
-+ return;
-+ }
-+ }
-+ out:
-+ if(buf != default_buf)
-+ kfree(buf);
-+
-+}
-+
-+void mconsole_config(struct mc_request *req)
-+{
-+ struct mc_device *dev;
-+ char *ptr = req->request.data, *name;
-+ int err;
-+
-+ ptr += strlen("config");
-+ while(isspace(*ptr)) ptr++;
-+ dev = mconsole_find_dev(ptr);
-+ if(dev == NULL){
-+ mconsole_reply(req, "Bad configuration option", 1, 0);
-+ return;
-+ }
-+
-+ name = &ptr[strlen(dev->name)];
-+ ptr = name;
-+ while((*ptr != '=') && (*ptr != '\0'))
-+ ptr++;
-+
-+ if(*ptr == '='){
-+ err = (*dev->config)(name);
-+ mconsole_reply(req, "", err, 0);
-+ }
-+ else mconsole_get_config(dev->get_config, req, name);
-+}
-+
-+void mconsole_remove(struct mc_request *req)
-+{
-+ struct mc_device *dev;
-+ char *ptr = req->request.data;
-+ int err;
-+
-+ ptr += strlen("remove");
-+ while(isspace(*ptr)) ptr++;
-+ dev = mconsole_find_dev(ptr);
-+ if(dev == NULL){
-+ mconsole_reply(req, "Bad remove option", 1, 0);
-+ return;
-+ }
-+ err = (*dev->remove)(&ptr[strlen(dev->name)]);
-+ mconsole_reply(req, "", err, 0);
-+}
-+
-+#ifdef CONFIG_MAGIC_SYSRQ
-+void mconsole_sysrq(struct mc_request *req)
-+{
-+ char *ptr = req->request.data;
-+
-+ ptr += strlen("sysrq");
-+ while(isspace(*ptr)) ptr++;
-+
-+ mconsole_reply(req, "", 0, 0);
-+ handle_sysrq(*ptr, ¤t->thread.regs, NULL, NULL);
-+}
-+#else
-+void mconsole_sysrq(struct mc_request *req)
-+{
-+ mconsole_reply(req, "Sysrq not compiled in", 1, 0);
-+}
-+#endif
-+
-+/* Changed by mconsole_setup, which is __setup, and called before SMP is
-+ * active.
-+ */
-+static char *notify_socket = NULL;
-+
-+int mconsole_init(void)
-+{
-+ int err, sock;
-+ char file[256];
-+
-+ if(umid_file_name("mconsole", file, sizeof(file))) return(-1);
-+ snprintf(mconsole_socket_name, sizeof(file), "%s", file);
-+
-+ sock = os_create_unix_socket(file, sizeof(file), 1);
-+ if (sock < 0){
-+ printk("Failed to initialize management console\n");
-+ return(1);
-+ }
-+
-+ register_reboot_notifier(&reboot_notifier);
-+
-+ err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt,
-+ SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
-+ "mconsole", (void *)sock);
-+ if (err){
-+ printk("Failed to get IRQ for management console\n");
-+ return(1);
-+ }
-+
-+ if(notify_socket != NULL){
-+ notify_socket = uml_strdup(notify_socket);
-+ if(notify_socket != NULL)
-+ mconsole_notify(notify_socket, MCONSOLE_SOCKET,
-+ mconsole_socket_name,
-+ strlen(mconsole_socket_name) + 1);
-+ else printk(KERN_ERR "mconsole_setup failed to strdup "
-+ "string\n");
-+ }
-+
-+ printk("mconsole (version %d) initialized on %s\n",
-+ MCONSOLE_VERSION, mconsole_socket_name);
-+ return(0);
-+}
-+
-+__initcall(mconsole_init);
-+
-+static int write_proc_mconsole(struct file *file, const char *buffer,
-+ unsigned long count, void *data)
-+{
-+ char *buf;
-+
-+ buf = kmalloc(count + 1, GFP_KERNEL);
-+ if(buf == NULL)
-+ return(-ENOMEM);
-+
-+ if(copy_from_user(buf, buffer, count)){
-+ count = -EFAULT;
-+ goto out;
-+ }
-+
-+ buf[count] = '\0';
-+
-+ mconsole_notify(notify_socket, MCONSOLE_USER_NOTIFY, buf, count);
-+ out:
-+ kfree(buf);
-+ return(count);
-+}
-+
-+static int create_proc_mconsole(void)
-+{
-+ struct proc_dir_entry *ent;
-+
-+ if(notify_socket == NULL) return(0);
-+
-+ ent = create_proc_entry("mconsole", S_IFREG | 0200, NULL);
-+ if(ent == NULL){
-+ printk("create_proc_mconsole : create_proc_entry failed\n");
-+ return(0);
-+ }
-+
-+ ent->read_proc = NULL;
-+ ent->write_proc = write_proc_mconsole;
-+ return(0);
-+}
-+
-+static spinlock_t notify_spinlock = SPIN_LOCK_UNLOCKED;
-+
-+void lock_notify(void)
-+{
-+ spin_lock(¬ify_spinlock);
-+}
-+
-+void unlock_notify(void)
-+{
-+ spin_unlock(¬ify_spinlock);
-+}
-+
-+__initcall(create_proc_mconsole);
-+
-+#define NOTIFY "=notify:"
-+
-+static int mconsole_setup(char *str)
-+{
-+ if(!strncmp(str, NOTIFY, strlen(NOTIFY))){
-+ str += strlen(NOTIFY);
-+ notify_socket = str;
-+ }
-+ else printk(KERN_ERR "mconsole_setup : Unknown option - '%s'\n", str);
-+ return(1);
-+}
-+
-+__setup("mconsole", mconsole_setup);
-+
-+__uml_help(mconsole_setup,
-+"mconsole=notify:<socket>\n"
-+" Requests that the mconsole driver send a message to the named Unix\n"
-+" socket containing the name of the mconsole socket. This also serves\n"
-+" to notify outside processes when UML has booted far enough to respond\n"
-+" to mconsole requests.\n\n"
-+);
-+
-+static int notify_panic(struct notifier_block *self, unsigned long unused1,
-+ void *ptr)
-+{
-+ char *message = ptr;
-+
-+ if(notify_socket == NULL) return(0);
-+
-+ mconsole_notify(notify_socket, MCONSOLE_PANIC, message,
-+ strlen(message) + 1);
-+ return(0);
-+}
-+
-+static struct notifier_block panic_exit_notifier = {
-+ .notifier_call = notify_panic,
-+ .next = NULL,
-+ .priority = 1
-+};
-+
-+static int add_notifier(void)
-+{
-+ notifier_chain_register(&panic_notifier_list, &panic_exit_notifier);
-+ return(0);
-+}
-+
-+__initcall(add_notifier);
-+
-+char *mconsole_notify_socket(void)
-+{
-+ return(notify_socket);
-+}
-+
-+EXPORT_SYMBOL(mconsole_notify_socket);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/mconsole_user.c um/arch/um/drivers/mconsole_user.c
---- orig/arch/um/drivers/mconsole_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/mconsole_user.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,215 @@
-+/*
-+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
-+ * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <errno.h>
-+#include <signal.h>
-+#include <sys/socket.h>
-+#include <sys/types.h>
-+#include <sys/uio.h>
-+#include <sys/un.h>
-+#include <unistd.h>
-+#include "user.h"
-+#include "mconsole.h"
-+#include "umid.h"
-+
-+static struct mconsole_command commands[] = {
-+ { "version", mconsole_version, MCONSOLE_INTR },
-+ { "halt", mconsole_halt, MCONSOLE_PROC },
-+ { "reboot", mconsole_reboot, MCONSOLE_PROC },
-+ { "config", mconsole_config, MCONSOLE_PROC },
-+ { "remove", mconsole_remove, MCONSOLE_PROC },
-+ { "sysrq", mconsole_sysrq, MCONSOLE_INTR },
-+ { "help", mconsole_help, MCONSOLE_INTR },
-+ { "cad", mconsole_cad, MCONSOLE_INTR },
-+ { "stop", mconsole_stop, MCONSOLE_PROC },
-+ { "go", mconsole_go, MCONSOLE_INTR },
-+ { "log", mconsole_log, MCONSOLE_INTR },
-+ { "proc", mconsole_proc, MCONSOLE_PROC },
-+};
-+
-+/* Initialized in mconsole_init, which is an initcall */
-+char mconsole_socket_name[256];
-+
-+int mconsole_reply_v0(struct mc_request *req, char *reply)
-+{
-+ struct iovec iov;
-+ struct msghdr msg;
-+
-+ iov.iov_base = reply;
-+ iov.iov_len = strlen(reply);
-+
-+ msg.msg_name = &(req->origin);
-+ msg.msg_namelen = req->originlen;
-+ msg.msg_iov = &iov;
-+ msg.msg_iovlen = 1;
-+ msg.msg_control = NULL;
-+ msg.msg_controllen = 0;
-+ msg.msg_flags = 0;
-+
-+ return sendmsg(req->originating_fd, &msg, 0);
-+}
-+
-+static struct mconsole_command *mconsole_parse(struct mc_request *req)
-+{
-+ struct mconsole_command *cmd;
-+ int i;
-+
-+ for(i=0;i<sizeof(commands)/sizeof(commands[0]);i++){
-+ cmd = &commands[i];
-+ if(!strncmp(req->request.data, cmd->command,
-+ strlen(cmd->command))){
-+ return(cmd);
-+ }
-+ }
-+ return(NULL);
-+}
-+
-+#define MIN(a,b) ((a)<(b) ? (a):(b))
-+
-+#define STRINGX(x) #x
-+#define STRING(x) STRINGX(x)
-+
-+int mconsole_get_request(int fd, struct mc_request *req)
-+{
-+ int len;
-+
-+ req->originlen = sizeof(req->origin);
-+ req->len = recvfrom(fd, &req->request, sizeof(req->request), 0,
-+ (struct sockaddr *) req->origin, &req->originlen);
-+ if (req->len < 0)
-+ return 0;
-+
-+ req->originating_fd = fd;
-+
-+ if(req->request.magic != MCONSOLE_MAGIC){
-+ /* Unversioned request */
-+ len = MIN(sizeof(req->request.data) - 1,
-+ strlen((char *) &req->request));
-+ memmove(req->request.data, &req->request, len);
-+ req->request.data[len] = '\0';
-+
-+ req->request.magic = MCONSOLE_MAGIC;
-+ req->request.version = 0;
-+ req->request.len = len;
-+
-+ mconsole_reply_v0(req, "ERR Version 0 mconsole clients are "
-+ "not supported by this driver");
-+ return(0);
-+ }
-+
-+ if(req->request.len >= MCONSOLE_MAX_DATA){
-+ mconsole_reply(req, "Request too large", 1, 0);
-+ return(0);
-+ }
-+ if(req->request.version != MCONSOLE_VERSION){
-+ mconsole_reply(req, "This driver only supports version "
-+ STRING(MCONSOLE_VERSION) " clients", 1, 0);
-+ }
-+
-+ req->request.data[req->request.len] = '\0';
-+ req->cmd = mconsole_parse(req);
-+ if(req->cmd == NULL){
-+ mconsole_reply(req, "Unknown command", 1, 0);
-+ return(0);
-+ }
-+
-+ return(1);
-+}
-+
-+int mconsole_reply(struct mc_request *req, char *str, int err, int more)
-+{
-+ struct mconsole_reply reply;
-+ int total, len, n;
-+
-+ total = strlen(str);
-+ do {
-+ reply.err = err;
-+
-+ /* err can only be true on the first packet */
-+ err = 0;
-+
-+ len = MIN(total, MCONSOLE_MAX_DATA - 1);
-+
-+ if(len == total) reply.more = more;
-+ else reply.more = 1;
-+
-+ memcpy(reply.data, str, len);
-+ reply.data[len] = '\0';
-+ total -= len;
-+ str += len;
-+ reply.len = len + 1;
-+
-+ len = sizeof(reply) + reply.len - sizeof(reply.data);
-+
-+ n = sendto(req->originating_fd, &reply, len, 0,
-+ (struct sockaddr *) req->origin, req->originlen);
-+
-+ if(n < 0) return(-errno);
-+ } while(total > 0);
-+ return(0);
-+}
-+
-+int mconsole_unlink_socket(void)
-+{
-+ unlink(mconsole_socket_name);
-+ return 0;
-+}
-+
-+static int notify_sock = -1;
-+
-+int mconsole_notify(char *sock_name, int type, const void *data, int len)
-+{
-+ struct sockaddr_un target;
-+ struct mconsole_notify packet;
-+ int n, err = 0;
-+
-+ lock_notify();
-+ if(notify_sock < 0){
-+ notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0);
-+ if(notify_sock < 0){
-+ printk("mconsole_notify - socket failed, errno = %d\n",
-+ errno);
-+ err = -errno;
-+ }
-+ }
-+ unlock_notify();
-+
-+ if(err)
-+ return(err);
-+
-+ target.sun_family = AF_UNIX;
-+ strcpy(target.sun_path, sock_name);
-+
-+ packet.magic = MCONSOLE_MAGIC;
-+ packet.version = MCONSOLE_VERSION;
-+ packet.type = type;
-+ len = (len > sizeof(packet.data)) ? sizeof(packet.data) : len;
-+ packet.len = len;
-+ memcpy(packet.data, data, len);
-+
-+ err = 0;
-+ len = sizeof(packet) + packet.len - sizeof(packet.data);
-+ n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target,
-+ sizeof(target));
-+ if(n < 0){
-+ printk("mconsole_notify - sendto failed, errno = %d\n", errno);
-+ err = -errno;
-+ }
-+ return(err);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/mmapper_kern.c um/arch/um/drivers/mmapper_kern.c
---- orig/arch/um/drivers/mmapper_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/mmapper_kern.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,151 @@
-+/*
-+ * arch/um/drivers/mmapper_kern.c
-+ *
-+ * BRIEF MODULE DESCRIPTION
-+ *
-+ * Copyright (C) 2000 RidgeRun, Inc.
-+ * Author: RidgeRun, Inc.
-+ * Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com
-+ *
-+ */
-+#include <linux/kdev_t.h>
-+#include <linux/time.h>
-+#include <linux/devfs_fs_kernel.h>
-+#include <linux/module.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <asm/uaccess.h>
-+#include <asm/irq.h>
-+#include <asm/smplock.h>
-+#include <asm/pgtable.h>
-+#include "mem_user.h"
-+#include "user_util.h"
-+
-+/* These are set in mmapper_init, which is called at boot time */
-+static unsigned long mmapper_size;
-+static unsigned long p_buf = 0;
-+static char *v_buf = NULL;
-+
-+static ssize_t
-+mmapper_read(struct file *file, char *buf, size_t count, loff_t *ppos)
-+{
-+ if(*ppos > mmapper_size)
-+ return -EINVAL;
-+
-+ if(count + *ppos > mmapper_size)
-+ count = count + *ppos - mmapper_size;
-+
-+ if(count < 0)
-+ return -EINVAL;
-+
-+ copy_to_user(buf,&v_buf[*ppos],count);
-+
-+ return count;
-+}
-+
-+static ssize_t
-+mmapper_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-+{
-+ if(*ppos > mmapper_size)
-+ return -EINVAL;
-+
-+ if(count + *ppos > mmapper_size)
-+ count = count + *ppos - mmapper_size;
-+
-+ if(count < 0)
-+ return -EINVAL;
-+
-+ copy_from_user(&v_buf[*ppos],buf,count);
-+
-+ return count;
-+}
-+
-+static int
-+mmapper_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ return(-ENOIOCTLCMD);
-+}
-+
-+static int
-+mmapper_mmap(struct file *file, struct vm_area_struct * vma)
-+{
-+ int ret = -EINVAL;
-+ int size;
-+
-+ lock_kernel();
-+ if (vma->vm_pgoff != 0)
-+ goto out;
-+
-+ size = vma->vm_end - vma->vm_start;
-+ if(size > mmapper_size) return(-EFAULT);
-+
-+ /* XXX A comment above remap_page_range says it should only be
-+ * called when the mm semaphore is held
-+ */
-+ if (remap_page_range(vma->vm_start, p_buf, size, vma->vm_page_prot))
-+ goto out;
-+ ret = 0;
-+out:
-+ unlock_kernel();
-+ return ret;
-+}
-+
-+static int
-+mmapper_open(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static int
-+mmapper_release(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static struct file_operations mmapper_fops = {
-+ .owner = THIS_MODULE,
-+ .read = mmapper_read,
-+ .write = mmapper_write,
-+ .ioctl = mmapper_ioctl,
-+ .mmap = mmapper_mmap,
-+ .open = mmapper_open,
-+ .release = mmapper_release,
-+};
-+
-+static int __init mmapper_init(void)
-+{
-+ printk(KERN_INFO "Mapper v0.1\n");
-+
-+ v_buf = (char *) find_iomem("mmapper", &mmapper_size);
-+ if(mmapper_size == 0){
-+ printk(KERN_ERR "mmapper_init - find_iomem failed\n");
-+ return(0);
-+ }
-+
-+ p_buf = __pa(v_buf);
-+
-+ devfs_register (NULL, "mmapper", DEVFS_FL_DEFAULT,
-+ 30, 0, S_IFCHR | S_IRUGO | S_IWUGO,
-+ &mmapper_fops, NULL);
-+ devfs_mk_symlink(NULL, "mmapper0", DEVFS_FL_DEFAULT, "mmapper",
-+ NULL, NULL);
-+ return(0);
-+}
-+
-+static void mmapper_exit(void)
-+{
-+}
-+
-+module_init(mmapper_init);
-+module_exit(mmapper_exit);
-+
-+MODULE_AUTHOR("Greg Lonnon <glonnon@ridgerun.com>");
-+MODULE_DESCRIPTION("DSPLinux simulator mmapper driver");
-+/*
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/net_kern.c um/arch/um/drivers/net_kern.c
---- orig/arch/um/drivers/net_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/net_kern.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,872 @@
-+/*
-+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
-+ * James Leu (jleu@mindspring.net).
-+ * Copyright (C) 2001 by various other people who didn't put their name here.
-+ * Licensed under the GPL.
-+ */
-+
-+#include "linux/config.h"
-+#include "linux/kernel.h"
-+#include "linux/netdevice.h"
-+#include "linux/rtnetlink.h"
-+#include "linux/skbuff.h"
-+#include "linux/socket.h"
-+#include "linux/spinlock.h"
-+#include "linux/module.h"
-+#include "linux/init.h"
-+#include "linux/etherdevice.h"
-+#include "linux/list.h"
-+#include "linux/inetdevice.h"
-+#include "linux/ctype.h"
-+#include "linux/bootmem.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "net_kern.h"
-+#include "net_user.h"
-+#include "mconsole_kern.h"
-+#include "init.h"
-+#include "irq_user.h"
-+#include "irq_kern.h"
-+
-+static spinlock_t opened_lock = SPIN_LOCK_UNLOCKED;
-+LIST_HEAD(opened);
-+
-+static int uml_net_rx(struct net_device *dev)
-+{
-+ struct uml_net_private *lp = dev->priv;
-+ int pkt_len;
-+ struct sk_buff *skb;
-+
-+ /* If we can't allocate memory, try again next round. */
-+ skb = dev_alloc_skb(dev->mtu);
-+ if (skb == NULL) {
-+ lp->stats.rx_dropped++;
-+ return 0;
-+ }
-+
-+ skb->dev = dev;
-+ skb_put(skb, dev->mtu);
-+ skb->mac.raw = skb->data;
-+ pkt_len = (*lp->read)(lp->fd, &skb, lp);
-+
-+ if (pkt_len > 0) {
-+ skb_trim(skb, pkt_len);
-+ skb->protocol = (*lp->protocol)(skb);
-+ netif_rx(skb);
-+
-+ lp->stats.rx_bytes += skb->len;
-+ lp->stats.rx_packets++;
-+ return pkt_len;
-+ }
-+
-+ kfree_skb(skb);
-+ return pkt_len;
-+}
-+
-+void uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct net_device *dev = dev_id;
-+ struct uml_net_private *lp = dev->priv;
-+ int err;
-+
-+ if(!netif_running(dev))
-+ return;
-+
-+ spin_lock(&lp->lock);
-+ while((err = uml_net_rx(dev)) > 0) ;
-+ if(err < 0) {
-+ printk(KERN_ERR
-+ "Device '%s' read returned %d, shutting it down\n",
-+ dev->name, err);
-+ dev_close(dev);
-+ goto out;
-+ }
-+ reactivate_fd(lp->fd, UM_ETH_IRQ);
-+
-+ out:
-+ spin_unlock(&lp->lock);
-+}
-+
-+static int uml_net_open(struct net_device *dev)
-+{
-+ struct uml_net_private *lp = dev->priv;
-+ char addr[sizeof("255.255.255.255\0")];
-+ int err;
-+
-+ spin_lock(&lp->lock);
-+
-+ if(lp->fd >= 0){
-+ err = -ENXIO;
-+ goto out;
-+ }
-+
-+ if(!lp->have_mac){
-+ dev_ip_addr(dev, addr, &lp->mac[2]);
-+ set_ether_mac(dev, lp->mac);
-+ }
-+
-+ lp->fd = (*lp->open)(&lp->user);
-+ if(lp->fd < 0){
-+ err = lp->fd;
-+ goto out;
-+ }
-+
-+ err = um_request_irq(dev->irq, lp->fd, IRQ_READ, uml_net_interrupt,
-+ SA_INTERRUPT | SA_SHIRQ, dev->name, dev);
-+ if(err != 0){
-+ printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err);
-+ if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user);
-+ lp->fd = -1;
-+ err = -ENETUNREACH;
-+ }
-+
-+ lp->tl.data = (unsigned long) &lp->user;
-+ netif_start_queue(dev);
-+
-+ spin_lock(&opened_lock);
-+ list_add(&lp->list, &opened);
-+ spin_unlock(&opened_lock);
-+ MOD_INC_USE_COUNT;
-+ out:
-+ spin_unlock(&lp->lock);
-+ return(err);
-+}
-+
-+static int uml_net_close(struct net_device *dev)
-+{
-+ struct uml_net_private *lp = dev->priv;
-+
-+ netif_stop_queue(dev);
-+ spin_lock(&lp->lock);
-+
-+ free_irq(dev->irq, dev);
-+ if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user);
-+ lp->fd = -1;
-+ spin_lock(&opened_lock);
-+ list_del(&lp->list);
-+ spin_unlock(&opened_lock);
-+
-+ MOD_DEC_USE_COUNT;
-+ spin_unlock(&lp->lock);
-+ return 0;
-+}
-+
-+static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+ struct uml_net_private *lp = dev->priv;
-+ unsigned long flags;
-+ int len;
-+
-+ netif_stop_queue(dev);
-+
-+ spin_lock_irqsave(&lp->lock, flags);
-+
-+ len = (*lp->write)(lp->fd, &skb, lp);
-+
-+ if(len == skb->len) {
-+ lp->stats.tx_packets++;
-+ lp->stats.tx_bytes += skb->len;
-+ dev->trans_start = jiffies;
-+ netif_start_queue(dev);
-+
-+ /* this is normally done in the interrupt when tx finishes */
-+ netif_wake_queue(dev);
-+ }
-+ else if(len == 0){
-+ netif_start_queue(dev);
-+ lp->stats.tx_dropped++;
-+ }
-+ else {
-+ netif_start_queue(dev);
-+ printk(KERN_ERR "uml_net_start_xmit: failed(%d)\n", len);
-+ }
-+
-+ spin_unlock_irqrestore(&lp->lock, flags);
-+
-+ dev_kfree_skb(skb);
-+
-+ return 0;
-+}
-+
-+static struct net_device_stats *uml_net_get_stats(struct net_device *dev)
-+{
-+ struct uml_net_private *lp = dev->priv;
-+ return &lp->stats;
-+}
-+
-+static void uml_net_set_multicast_list(struct net_device *dev)
-+{
-+ if (dev->flags & IFF_PROMISC) return;
-+ else if (dev->mc_count) dev->flags |= IFF_ALLMULTI;
-+ else dev->flags &= ~IFF_ALLMULTI;
-+}
-+
-+static void uml_net_tx_timeout(struct net_device *dev)
-+{
-+ dev->trans_start = jiffies;
-+ netif_wake_queue(dev);
-+}
-+
-+static int uml_net_set_mac(struct net_device *dev, void *addr)
-+{
-+ struct uml_net_private *lp = dev->priv;
-+ struct sockaddr *hwaddr = addr;
-+
-+ spin_lock(&lp->lock);
-+ memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN);
-+ spin_unlock(&lp->lock);
-+
-+ return(0);
-+}
-+
-+static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
-+{
-+ struct uml_net_private *lp = dev->priv;
-+ int err = 0;
-+
-+ spin_lock(&lp->lock);
-+
-+ new_mtu = (*lp->set_mtu)(new_mtu, &lp->user);
-+ if(new_mtu < 0){
-+ err = new_mtu;
-+ goto out;
-+ }
-+
-+ dev->mtu = new_mtu;
-+
-+ out:
-+ spin_unlock(&lp->lock);
-+ return err;
-+}
-+
-+static int uml_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-+{
-+ return(-EINVAL);
-+}
-+
-+void uml_net_user_timer_expire(unsigned long _conn)
-+{
-+#ifdef undef
-+ struct connection *conn = (struct connection *)_conn;
-+
-+ dprintk(KERN_INFO "uml_net_user_timer_expire [%p]\n", conn);
-+ do_connect(conn);
-+#endif
-+}
-+
-+/*
-+ * default do nothing hard header packet routines for struct net_device init.
-+ * real ethernet transports will overwrite with real routines.
-+ */
-+static int uml_net_hard_header(struct sk_buff *skb, struct net_device *dev,
-+ unsigned short type, void *daddr, void *saddr, unsigned len)
-+{
-+ return(0); /* no change */
-+}
-+
-+static int uml_net_rebuild_header(struct sk_buff *skb)
-+{
-+ return(0); /* ignore */
-+}
-+
-+static int uml_net_header_cache(struct neighbour *neigh, struct hh_cache *hh)
-+{
-+ return(-1); /* fail */
-+}
-+
-+static void uml_net_header_cache_update(struct hh_cache *hh,
-+ struct net_device *dev, unsigned char * haddr)
-+{
-+ /* ignore */
-+}
-+
-+static int uml_net_header_parse(struct sk_buff *skb, unsigned char *haddr)
-+{
-+ return(0); /* nothing */
-+}
-+
-+static spinlock_t devices_lock = SPIN_LOCK_UNLOCKED;
-+static struct list_head devices = LIST_HEAD_INIT(devices);
-+
-+static int eth_configure(int n, void *init, char *mac,
-+ struct transport *transport)
-+{
-+ struct uml_net *device;
-+ struct net_device *dev;
-+ struct uml_net_private *lp;
-+ int save, err, size;
-+
-+ size = transport->private_size + sizeof(struct uml_net_private) +
-+ sizeof(((struct uml_net_private *) 0)->user);
-+
-+ device = kmalloc(sizeof(*device), GFP_KERNEL);
-+ if(device == NULL){
-+ printk(KERN_ERR "eth_configure failed to allocate uml_net\n");
-+ return(1);
-+ }
-+
-+ *device = ((struct uml_net) { .list = LIST_HEAD_INIT(device->list),
-+ .dev = NULL,
-+ .index = n,
-+ .mac = { [ 0 ... 5 ] = 0 },
-+ .have_mac = 0 });
-+
-+ spin_lock(&devices_lock);
-+ list_add(&device->list, &devices);
-+ spin_unlock(&devices_lock);
-+
-+ if(setup_etheraddr(mac, device->mac))
-+ device->have_mac = 1;
-+
-+ printk(KERN_INFO "Netdevice %d ", n);
-+ if(device->have_mac) printk("(%02x:%02x:%02x:%02x:%02x:%02x) ",
-+ device->mac[0], device->mac[1],
-+ device->mac[2], device->mac[3],
-+ device->mac[4], device->mac[5]);
-+ printk(": ");
-+ dev = kmalloc(sizeof(*dev) + size, GFP_KERNEL);
-+ if(dev == NULL){
-+ printk(KERN_ERR "eth_configure: failed to allocate device\n");
-+ return(1);
-+ }
-+ memset(dev, 0, sizeof(*dev) + size);
-+
-+ snprintf(dev->name, sizeof(dev->name), "eth%d", n);
-+ dev->priv = (void *) &dev[1];
-+ device->dev = dev;
-+
-+ dev->hard_header = uml_net_hard_header;
-+ dev->rebuild_header = uml_net_rebuild_header;
-+ dev->hard_header_cache = uml_net_header_cache;
-+ dev->header_cache_update= uml_net_header_cache_update;
-+ dev->hard_header_parse = uml_net_header_parse;
-+
-+ (*transport->kern->init)(dev, init);
-+
-+ dev->mtu = transport->user->max_packet;
-+ dev->open = uml_net_open;
-+ dev->hard_start_xmit = uml_net_start_xmit;
-+ dev->stop = uml_net_close;
-+ dev->get_stats = uml_net_get_stats;
-+ dev->set_multicast_list = uml_net_set_multicast_list;
-+ dev->tx_timeout = uml_net_tx_timeout;
-+ dev->set_mac_address = uml_net_set_mac;
-+ dev->change_mtu = uml_net_change_mtu;
-+ dev->do_ioctl = uml_net_ioctl;
-+ dev->watchdog_timeo = (HZ >> 1);
-+ dev->irq = UM_ETH_IRQ;
-+
-+ rtnl_lock();
-+ err = register_netdevice(dev);
-+ rtnl_unlock();
-+ if(err)
-+ return(1);
-+ lp = dev->priv;
-+
-+ /* lp.user is the first four bytes of the transport data, which
-+ * has already been initialized. This structure assignment will
-+ * overwrite that, so we make sure that .user gets overwritten with
-+ * what it already has.
-+ */
-+ save = lp->user[0];
-+ *lp = ((struct uml_net_private)
-+ { .list = LIST_HEAD_INIT(lp->list),
-+ .lock = SPIN_LOCK_UNLOCKED,
-+ .dev = dev,
-+ .fd = -1,
-+ .mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0},
-+ .have_mac = device->have_mac,
-+ .protocol = transport->kern->protocol,
-+ .open = transport->user->open,
-+ .close = transport->user->close,
-+ .remove = transport->user->remove,
-+ .read = transport->kern->read,
-+ .write = transport->kern->write,
-+ .add_address = transport->user->add_address,
-+ .delete_address = transport->user->delete_address,
-+ .set_mtu = transport->user->set_mtu,
-+ .user = { save } });
-+ init_timer(&lp->tl);
-+ lp->tl.function = uml_net_user_timer_expire;
-+ memset(&lp->stats, 0, sizeof(lp->stats));
-+ if(lp->have_mac) memcpy(lp->mac, device->mac, sizeof(lp->mac));
-+
-+ if(transport->user->init)
-+ (*transport->user->init)(&lp->user, dev);
-+
-+ if(device->have_mac)
-+ set_ether_mac(dev, device->mac);
-+ return(0);
-+}
-+
-+static struct uml_net *find_device(int n)
-+{
-+ struct uml_net *device;
-+ struct list_head *ele;
-+
-+ spin_lock(&devices_lock);
-+ list_for_each(ele, &devices){
-+ device = list_entry(ele, struct uml_net, list);
-+ if(device->index == n)
-+ goto out;
-+ }
-+ device = NULL;
-+ out:
-+ spin_unlock(&devices_lock);
-+ return(device);
-+}
-+
-+static int eth_parse(char *str, int *index_out, char **str_out)
-+{
-+ char *end;
-+ int n;
-+
-+ n = simple_strtoul(str, &end, 0);
-+ if(end == str){
-+ printk(KERN_ERR "eth_setup: Failed to parse '%s'\n", str);
-+ return(1);
-+ }
-+ if(n < 0){
-+ printk(KERN_ERR "eth_setup: device %d is negative\n", n);
-+ return(1);
-+ }
-+ str = end;
-+ if(*str != '='){
-+ printk(KERN_ERR
-+ "eth_setup: expected '=' after device number\n");
-+ return(1);
-+ }
-+ str++;
-+ if(find_device(n)){
-+ printk(KERN_ERR "eth_setup: Device %d already configured\n",
-+ n);
-+ return(1);
-+ }
-+ if(index_out) *index_out = n;
-+ *str_out = str;
-+ return(0);
-+}
-+
-+struct eth_init {
-+ struct list_head list;
-+ char *init;
-+ int index;
-+};
-+
-+/* Filled in at boot time. Will need locking if the transports become
-+ * modular.
-+ */
-+struct list_head transports = LIST_HEAD_INIT(transports);
-+
-+/* Filled in during early boot */
-+struct list_head eth_cmd_line = LIST_HEAD_INIT(eth_cmd_line);
-+
-+static int check_transport(struct transport *transport, char *eth, int n,
-+ void **init_out, char **mac_out)
-+{
-+ int len;
-+
-+ len = strlen(transport->name);
-+ if(strncmp(eth, transport->name, len))
-+ return(0);
-+
-+ eth += len;
-+ if(*eth == ',')
-+ eth++;
-+ else if(*eth != '\0')
-+ return(0);
-+
-+ *init_out = kmalloc(transport->setup_size, GFP_KERNEL);
-+ if(*init_out == NULL)
-+ return(1);
-+
-+ if(!transport->setup(eth, mac_out, *init_out)){
-+ kfree(*init_out);
-+ *init_out = NULL;
-+ }
-+ return(1);
-+}
-+
-+void register_transport(struct transport *new)
-+{
-+ struct list_head *ele, *next;
-+ struct eth_init *eth;
-+ void *init;
-+ char *mac = NULL;
-+ int match;
-+
-+ list_add(&new->list, &transports);
-+
-+ list_for_each_safe(ele, next, ð_cmd_line){
-+ eth = list_entry(ele, struct eth_init, list);
-+ match = check_transport(new, eth->init, eth->index, &init,
-+ &mac);
-+ if(!match)
-+ continue;
-+ else if(init != NULL){
-+ eth_configure(eth->index, init, mac, new);
-+ kfree(init);
-+ }
-+ list_del(ð->list);
-+ }
-+}
-+
-+static int eth_setup_common(char *str, int index)
-+{
-+ struct list_head *ele;
-+ struct transport *transport;
-+ void *init;
-+ char *mac = NULL;
-+
-+ list_for_each(ele, &transports){
-+ transport = list_entry(ele, struct transport, list);
-+ if(!check_transport(transport, str, index, &init, &mac))
-+ continue;
-+ if(init != NULL){
-+ eth_configure(index, init, mac, transport);
-+ kfree(init);
-+ }
-+ return(1);
-+ }
-+ return(0);
-+}
-+
-+static int eth_setup(char *str)
-+{
-+ struct eth_init *new;
-+ int n, err;
-+
-+ err = eth_parse(str, &n, &str);
-+ if(err) return(1);
-+
-+ new = alloc_bootmem(sizeof(new));
-+ if(new == NULL){
-+ printk("eth_init : alloc_bootmem failed\n");
-+ return(1);
-+ }
-+ *new = ((struct eth_init) { .list = LIST_HEAD_INIT(new->list),
-+ .index = n,
-+ .init = str });
-+ list_add_tail(&new->list, ð_cmd_line);
-+ return(1);
-+}
-+
-+__setup("eth", eth_setup);
-+__uml_help(eth_setup,
-+"eth[0-9]+=<transport>,<options>\n"
-+" Configure a network device.\n\n"
-+);
-+
-+static int eth_init(void)
-+{
-+ struct list_head *ele, *next;
-+ struct eth_init *eth;
-+
-+ list_for_each_safe(ele, next, ð_cmd_line){
-+ eth = list_entry(ele, struct eth_init, list);
-+
-+ if(eth_setup_common(eth->init, eth->index))
-+ list_del(ð->list);
-+ }
-+
-+ return(1);
-+}
-+
-+__initcall(eth_init);
-+
-+static int net_config(char *str)
-+{
-+ int n, err;
-+
-+ err = eth_parse(str, &n, &str);
-+ if(err) return(err);
-+
-+ str = uml_strdup(str);
-+ if(str == NULL){
-+ printk(KERN_ERR "net_config failed to strdup string\n");
-+ return(-1);
-+ }
-+ err = !eth_setup_common(str, n);
-+ if(err)
-+ kfree(str);
-+ return(err);
-+}
-+
-+static int net_remove(char *str)
-+{
-+ struct uml_net *device;
-+ struct net_device *dev;
-+ struct uml_net_private *lp;
-+ char *end;
-+ int n;
-+
-+ n = simple_strtoul(str, &end, 0);
-+ if((*end != '\0') || (end == str))
-+ return(-1);
-+
-+ device = find_device(n);
-+ if(device == NULL)
-+ return(0);
-+
-+ dev = device->dev;
-+ lp = dev->priv;
-+ if(lp->fd > 0) return(-1);
-+ if(lp->remove != NULL) (*lp->remove)(&lp->user);
-+ unregister_netdev(dev);
-+
-+ list_del(&device->list);
-+ kfree(device);
-+ return(0);
-+}
-+
-+static struct mc_device net_mc = {
-+ .name = "eth",
-+ .config = net_config,
-+ .get_config = NULL,
-+ .remove = net_remove,
-+};
-+
-+static int uml_inetaddr_event(struct notifier_block *this, unsigned long event,
-+ void *ptr)
-+{
-+ struct in_ifaddr *ifa = ptr;
-+ u32 addr = ifa->ifa_address;
-+ u32 netmask = ifa->ifa_mask;
-+ struct net_device *dev = ifa->ifa_dev->dev;
-+ struct uml_net_private *lp;
-+ void (*proc)(unsigned char *, unsigned char *, void *);
-+ unsigned char addr_buf[4], netmask_buf[4];
-+
-+ if(dev->open != uml_net_open) return(NOTIFY_DONE);
-+
-+ lp = dev->priv;
-+
-+ proc = NULL;
-+ switch (event){
-+ case NETDEV_UP:
-+ proc = lp->add_address;
-+ break;
-+ case NETDEV_DOWN:
-+ proc = lp->delete_address;
-+ break;
-+ }
-+ if(proc != NULL){
-+ addr_buf[0] = addr & 0xff;
-+ addr_buf[1] = (addr >> 8) & 0xff;
-+ addr_buf[2] = (addr >> 16) & 0xff;
-+ addr_buf[3] = addr >> 24;
-+ netmask_buf[0] = netmask & 0xff;
-+ netmask_buf[1] = (netmask >> 8) & 0xff;
-+ netmask_buf[2] = (netmask >> 16) & 0xff;
-+ netmask_buf[3] = netmask >> 24;
-+ (*proc)(addr_buf, netmask_buf, &lp->user);
-+ }
-+ return(NOTIFY_DONE);
-+}
-+
-+struct notifier_block uml_inetaddr_notifier = {
-+ .notifier_call = uml_inetaddr_event,
-+};
-+
-+static int uml_net_init(void)
-+{
-+ struct list_head *ele;
-+ struct uml_net_private *lp;
-+ struct in_device *ip;
-+ struct in_ifaddr *in;
-+
-+ mconsole_register_dev(&net_mc);
-+ register_inetaddr_notifier(¨_inetaddr_notifier);
-+
-+ /* Devices may have been opened already, so the uml_inetaddr_notifier
-+ * didn't get a chance to run for them. This fakes it so that
-+ * addresses which have already been set up get handled properly.
-+ */
-+ list_for_each(ele, &opened){
-+ lp = list_entry(ele, struct uml_net_private, list);
-+ ip = lp->dev->ip_ptr;
-+ if(ip == NULL) continue;
-+ in = ip->ifa_list;
-+ while(in != NULL){
-+ uml_inetaddr_event(NULL, NETDEV_UP, in);
-+ in = in->ifa_next;
-+ }
-+ }
-+
-+ return(0);
-+}
-+
-+__initcall(uml_net_init);
-+
-+static void close_devices(void)
-+{
-+ struct list_head *ele;
-+ struct uml_net_private *lp;
-+
-+ list_for_each(ele, &opened){
-+ lp = list_entry(ele, struct uml_net_private, list);
-+ if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user);
-+ if(lp->remove != NULL) (*lp->remove)(&lp->user);
-+ }
-+}
-+
-+__uml_exitcall(close_devices);
-+
-+int setup_etheraddr(char *str, unsigned char *addr)
-+{
-+ char *end;
-+ int i;
-+
-+ if(str == NULL)
-+ return(0);
-+ for(i=0;i<6;i++){
-+ addr[i] = simple_strtoul(str, &end, 16);
-+ if((end == str) ||
-+ ((*end != ':') && (*end != ',') && (*end != '\0'))){
-+ printk(KERN_ERR
-+ "setup_etheraddr: failed to parse '%s' "
-+ "as an ethernet address\n", str);
-+ return(0);
-+ }
-+ str = end + 1;
-+ }
-+ if(addr[0] & 1){
-+ printk(KERN_ERR
-+ "Attempt to assign a broadcast ethernet address to a "
-+ "device disallowed\n");
-+ return(0);
-+ }
-+ return(1);
-+}
-+
-+void dev_ip_addr(void *d, char *buf, char *bin_buf)
-+{
-+ struct net_device *dev = d;
-+ struct in_device *ip = dev->ip_ptr;
-+ struct in_ifaddr *in;
-+ u32 addr;
-+
-+ if((ip == NULL) || ((in = ip->ifa_list) == NULL)){
-+ printk(KERN_WARNING "dev_ip_addr - device not assigned an "
-+ "IP address\n");
-+ return;
-+ }
-+ addr = in->ifa_address;
-+ sprintf(buf, "%d.%d.%d.%d", addr & 0xff, (addr >> 8) & 0xff,
-+ (addr >> 16) & 0xff, addr >> 24);
-+ if(bin_buf){
-+ bin_buf[0] = addr & 0xff;
-+ bin_buf[1] = (addr >> 8) & 0xff;
-+ bin_buf[2] = (addr >> 16) & 0xff;
-+ bin_buf[3] = addr >> 24;
-+ }
-+}
-+
-+void set_ether_mac(void *d, unsigned char *addr)
-+{
-+ struct net_device *dev = d;
-+
-+ memcpy(dev->dev_addr, addr, ETH_ALEN);
-+}
-+
-+struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra)
-+{
-+ if((skb != NULL) && (skb_tailroom(skb) < extra)){
-+ struct sk_buff *skb2;
-+
-+ skb2 = skb_copy_expand(skb, 0, extra, GFP_ATOMIC);
-+ dev_kfree_skb(skb);
-+ skb = skb2;
-+ }
-+ if(skb != NULL) skb_put(skb, extra);
-+ return(skb);
-+}
-+
-+void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *,
-+ void *),
-+ void *arg)
-+{
-+ struct net_device *dev = d;
-+ struct in_device *ip = dev->ip_ptr;
-+ struct in_ifaddr *in;
-+ unsigned char address[4], netmask[4];
-+
-+ if(ip == NULL) return;
-+ in = ip->ifa_list;
-+ while(in != NULL){
-+ address[0] = in->ifa_address & 0xff;
-+ address[1] = (in->ifa_address >> 8) & 0xff;
-+ address[2] = (in->ifa_address >> 16) & 0xff;
-+ address[3] = in->ifa_address >> 24;
-+ netmask[0] = in->ifa_mask & 0xff;
-+ netmask[1] = (in->ifa_mask >> 8) & 0xff;
-+ netmask[2] = (in->ifa_mask >> 16) & 0xff;
-+ netmask[3] = in->ifa_mask >> 24;
-+ (*cb)(address, netmask, arg);
-+ in = in->ifa_next;
-+ }
-+}
-+
-+int dev_netmask(void *d, void *m)
-+{
-+ struct net_device *dev = d;
-+ struct in_device *ip = dev->ip_ptr;
-+ struct in_ifaddr *in;
-+ __u32 *mask_out = m;
-+
-+ if(ip == NULL)
-+ return(1);
-+
-+ in = ip->ifa_list;
-+ if(in == NULL)
-+ return(1);
-+
-+ *mask_out = in->ifa_mask;
-+ return(0);
-+}
-+
-+void *get_output_buffer(int *len_out)
-+{
-+ void *ret;
-+
-+ ret = (void *) __get_free_pages(GFP_KERNEL, 0);
-+ if(ret) *len_out = PAGE_SIZE;
-+ else *len_out = 0;
-+ return(ret);
-+}
-+
-+void free_output_buffer(void *buffer)
-+{
-+ free_pages((unsigned long) buffer, 0);
-+}
-+
-+int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out,
-+ char **gate_addr)
-+{
-+ char *remain;
-+
-+ remain = split_if_spec(str, dev_name, mac_out, gate_addr, NULL);
-+ if(remain != NULL){
-+ printk("tap_setup_common - Extra garbage on specification : "
-+ "'%s'\n", remain);
-+ return(1);
-+ }
-+
-+ return(0);
-+}
-+
-+unsigned short eth_protocol(struct sk_buff *skb)
-+{
-+ return(eth_type_trans(skb, skb->dev));
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/net_user.c um/arch/um/drivers/net_user.c
---- orig/arch/um/drivers/net_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/net_user.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,252 @@
-+/*
-+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stddef.h>
-+#include <stdarg.h>
-+#include <unistd.h>
-+#include <stdio.h>
-+#include <errno.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <sys/socket.h>
-+#include <sys/wait.h>
-+#include "user.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "net_user.h"
-+#include "helper.h"
-+#include "os.h"
-+
-+int tap_open_common(void *dev, char *gate_addr)
-+{
-+ int tap_addr[4];
-+
-+ if(gate_addr == NULL) return(0);
-+ if(sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0],
-+ &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4){
-+ printk("Invalid tap IP address - '%s'\n", gate_addr);
-+ return(-EINVAL);
-+ }
-+ return(0);
-+}
-+
-+void tap_check_ips(char *gate_addr, char *eth_addr)
-+{
-+ int tap_addr[4];
-+
-+ if((gate_addr != NULL) &&
-+ (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0],
-+ &tap_addr[1], &tap_addr[2], &tap_addr[3]) == 4) &&
-+ (eth_addr[0] == tap_addr[0]) &&
-+ (eth_addr[1] == tap_addr[1]) &&
-+ (eth_addr[2] == tap_addr[2]) &&
-+ (eth_addr[3] == tap_addr[3])){
-+ printk("The tap IP address and the UML eth IP address"
-+ " must be different\n");
-+ }
-+}
-+
-+void read_output(int fd, char *output, int len)
-+{
-+ int remain, n, actual;
-+ char c;
-+
-+ if(output == NULL){
-+ output = &c;
-+ len = sizeof(c);
-+ }
-+
-+ *output = '\0';
-+ n = os_read_file(fd, &remain, sizeof(remain));
-+ if(n != sizeof(remain)){
-+ printk("read_output - read of length failed, err = %d\n", -n);
-+ return;
-+ }
-+
-+ while(remain != 0){
-+ n = (remain < len) ? remain : len;
-+ actual = os_read_file(fd, output, n);
-+ if(actual != n){
-+ printk("read_output - read of data failed, "
-+ "err = %d\n", -actual);
-+ return;
-+ }
-+ remain -= actual;
-+ }
-+ return;
-+}
-+
-+int net_read(int fd, void *buf, int len)
-+{
-+ int n;
-+
-+ n = os_read_file(fd, buf, len);
-+
-+ if(n == -EAGAIN)
-+ return(0);
-+ else if(n == 0)
-+ return(-ENOTCONN);
-+ return(n);
-+}
-+
-+int net_recvfrom(int fd, void *buf, int len)
-+{
-+ int n;
-+
-+ while(((n = recvfrom(fd, buf, len, 0, NULL, NULL)) < 0) &&
-+ (errno == EINTR)) ;
-+
-+ if(n < 0){
-+ if(errno == EAGAIN) return(0);
-+ return(-errno);
-+ }
-+ else if(n == 0) return(-ENOTCONN);
-+ return(n);
-+}
-+
-+int net_write(int fd, void *buf, int len)
-+{
-+ int n;
-+
-+ n = os_write_file(fd, buf, len);
-+
-+ if(n == -EAGAIN)
-+ return(0);
-+ else if(n == 0)
-+ return(-ENOTCONN);
-+ return(n);
-+}
-+
-+int net_send(int fd, void *buf, int len)
-+{
-+ int n;
-+
-+ while(((n = send(fd, buf, len, 0)) < 0) && (errno == EINTR)) ;
-+ if(n < 0){
-+ if(errno == EAGAIN) return(0);
-+ return(-errno);
-+ }
-+ else if(n == 0) return(-ENOTCONN);
-+ return(n);
-+}
-+
-+int net_sendto(int fd, void *buf, int len, void *to, int sock_len)
-+{
-+ int n;
-+
-+ while(((n = sendto(fd, buf, len, 0, (struct sockaddr *) to,
-+ sock_len)) < 0) && (errno == EINTR)) ;
-+ if(n < 0){
-+ if(errno == EAGAIN) return(0);
-+ return(-errno);
-+ }
-+ else if(n == 0) return(-ENOTCONN);
-+ return(n);
-+}
-+
-+struct change_pre_exec_data {
-+ int close_me;
-+ int stdout;
-+};
-+
-+static void change_pre_exec(void *arg)
-+{
-+ struct change_pre_exec_data *data = arg;
-+
-+ os_close_file(data->close_me);
-+ dup2(data->stdout, 1);
-+}
-+
-+static int change_tramp(char **argv, char *output, int output_len)
-+{
-+ int pid, fds[2], err;
-+ struct change_pre_exec_data pe_data;
-+
-+ err = os_pipe(fds, 1, 0);
-+ if(err < 0){
-+ printk("change_tramp - pipe failed, err = %d\n", -err);
-+ return(err);
-+ }
-+ pe_data.close_me = fds[0];
-+ pe_data.stdout = fds[1];
-+ pid = run_helper(change_pre_exec, &pe_data, argv, NULL);
-+
-+ os_close_file(fds[1]);
-+ read_output(fds[0], output, output_len);
-+ waitpid(pid, NULL, 0);
-+ return(pid);
-+}
-+
-+static void change(char *dev, char *what, unsigned char *addr,
-+ unsigned char *netmask)
-+{
-+ char addr_buf[sizeof("255.255.255.255\0")];
-+ char netmask_buf[sizeof("255.255.255.255\0")];
-+ char version[sizeof("nnnnn\0")];
-+ char *argv[] = { "uml_net", version, what, dev, addr_buf,
-+ netmask_buf, NULL };
-+ char *output;
-+ int output_len, pid;
-+
-+ sprintf(version, "%d", UML_NET_VERSION);
-+ sprintf(addr_buf, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
-+ sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1],
-+ netmask[2], netmask[3]);
-+
-+ output_len = page_size();
-+ output = um_kmalloc(output_len);
-+ if(output == NULL)
-+ printk("change : failed to allocate output buffer\n");
-+
-+ pid = change_tramp(argv, output, output_len);
-+ if(pid < 0) return;
-+
-+ if(output != NULL){
-+ printk("%s", output);
-+ kfree(output);
-+ }
-+}
-+
-+void open_addr(unsigned char *addr, unsigned char *netmask, void *arg)
-+{
-+ change(arg, "add", addr, netmask);
-+}
-+
-+void close_addr(unsigned char *addr, unsigned char *netmask, void *arg)
-+{
-+ change(arg, "del", addr, netmask);
-+}
-+
-+char *split_if_spec(char *str, ...)
-+{
-+ char **arg, *end;
-+ va_list ap;
-+
-+ va_start(ap, str);
-+ while((arg = va_arg(ap, char **)) != NULL){
-+ if(*str == '\0')
-+ return(NULL);
-+ end = strchr(str, ',');
-+ if(end != str)
-+ *arg = str;
-+ if(end == NULL)
-+ return(NULL);
-+ *end++ = '\0';
-+ str = end;
-+ }
-+ va_end(ap);
-+ return(str);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/null.c um/arch/um/drivers/null.c
---- orig/arch/um/drivers/null.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/null.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,55 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdlib.h>
-+#include <errno.h>
-+#include "chan_user.h"
-+#include "os.h"
-+
-+static int null_chan;
-+
-+void *null_init(char *str, int device, struct chan_opts *opts)
-+{
-+ return(&null_chan);
-+}
-+
-+int null_open(int input, int output, int primary, void *d, char **dev_out)
-+{
-+ *dev_out = NULL;
-+ return(os_open_file(DEV_NULL, of_rdwr(OPENFLAGS()), 0));
-+}
-+
-+int null_read(int fd, char *c_out, void *unused)
-+{
-+ return(-ENODEV);
-+}
-+
-+void null_free(void *data)
-+{
-+}
-+
-+struct chan_ops null_ops = {
-+ .type = "null",
-+ .init = null_init,
-+ .open = null_open,
-+ .close = generic_close,
-+ .read = null_read,
-+ .write = generic_write,
-+ .console_write = generic_console_write,
-+ .window_size = generic_window_size,
-+ .free = null_free,
-+ .winch = 0,
-+};
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/pcap_kern.c um/arch/um/drivers/pcap_kern.c
---- orig/arch/um/drivers/pcap_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/pcap_kern.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,127 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike <jdike@karaya.com>
-+ * Licensed under the GPL.
-+ */
-+
-+#include "linux/init.h"
-+#include "linux/netdevice.h"
-+#include "linux/etherdevice.h"
-+#include "net_kern.h"
-+#include "net_user.h"
-+#include "pcap_user.h"
-+
-+struct pcap_init {
-+ char *host_if;
-+ int promisc;
-+ int optimize;
-+ char *filter;
-+};
-+
-+void pcap_init(struct net_device *dev, void *data)
-+{
-+ struct uml_net_private *pri;
-+ struct pcap_data *ppri;
-+ struct pcap_init *init = data;
-+
-+ init_etherdev(dev, 0);
-+ pri = dev->priv;
-+ ppri = (struct pcap_data *) pri->user;
-+ *ppri = ((struct pcap_data)
-+ { .host_if = init->host_if,
-+ .promisc = init->promisc,
-+ .optimize = init->optimize,
-+ .filter = init->filter,
-+ .compiled = NULL,
-+ .pcap = NULL });
-+}
-+
-+static int pcap_read(int fd, struct sk_buff **skb,
-+ struct uml_net_private *lp)
-+{
-+ *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER);
-+ if(*skb == NULL) return(-ENOMEM);
-+ return(pcap_user_read(fd, (*skb)->mac.raw,
-+ (*skb)->dev->mtu + ETH_HEADER_OTHER,
-+ (struct pcap_data *) &lp->user));
-+}
-+
-+static int pcap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
-+{
-+ return(-EPERM);
-+}
-+
-+static struct net_kern_info pcap_kern_info = {
-+ .init = pcap_init,
-+ .protocol = eth_protocol,
-+ .read = pcap_read,
-+ .write = pcap_write,
-+};
-+
-+int pcap_setup(char *str, char **mac_out, void *data)
-+{
-+ struct pcap_init *init = data;
-+ char *remain, *host_if = NULL, *options[2] = { NULL, NULL };
-+ int i;
-+
-+ *init = ((struct pcap_init)
-+ { .host_if = "eth0",
-+ .promisc = 1,
-+ .optimize = 0,
-+ .filter = NULL });
-+
-+ remain = split_if_spec(str, &host_if, &init->filter,
-+ &options[0], &options[1], NULL);
-+ if(remain != NULL){
-+ printk(KERN_ERR "pcap_setup - Extra garbage on "
-+ "specification : '%s'\n", remain);
-+ return(0);
-+ }
-+
-+ if(host_if != NULL)
-+ init->host_if = host_if;
-+
-+ for(i = 0; i < sizeof(options)/sizeof(options[0]); i++){
-+ if(options[i] == NULL)
-+ continue;
-+ if(!strcmp(options[i], "promisc"))
-+ init->promisc = 1;
-+ else if(!strcmp(options[i], "nopromisc"))
-+ init->promisc = 0;
-+ else if(!strcmp(options[i], "optimize"))
-+ init->optimize = 1;
-+ else if(!strcmp(options[i], "nooptimize"))
-+ init->optimize = 0;
-+ else printk("pcap_setup : bad option - '%s'\n", options[i]);
-+ }
-+
-+ return(1);
-+}
-+
-+static struct transport pcap_transport = {
-+ .list = LIST_HEAD_INIT(pcap_transport.list),
-+ .name = "pcap",
-+ .setup = pcap_setup,
-+ .user = &pcap_user_info,
-+ .kern = &pcap_kern_info,
-+ .private_size = sizeof(struct pcap_data),
-+ .setup_size = sizeof(struct pcap_init),
-+};
-+
-+static int register_pcap(void)
-+{
-+ register_transport(&pcap_transport);
-+ return(1);
-+}
-+
-+__initcall(register_pcap);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/pcap_user.c um/arch/um/drivers/pcap_user.c
---- orig/arch/um/drivers/pcap_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/pcap_user.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,143 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike <jdike@karaya.com>
-+ * Licensed under the GPL.
-+ */
-+
-+#include <unistd.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <errno.h>
-+#include <pcap.h>
-+#include <asm/types.h>
-+#include "net_user.h"
-+#include "pcap_user.h"
-+#include "user.h"
-+
-+#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
-+
-+#define PCAP_FD(p) (*(int *)(p))
-+
-+static void pcap_user_init(void *data, void *dev)
-+{
-+ struct pcap_data *pri = data;
-+ pcap_t *p;
-+ char errors[PCAP_ERRBUF_SIZE];
-+
-+ p = pcap_open_live(pri->host_if, MAX_PACKET, pri->promisc, 0, errors);
-+ if(p == NULL){
-+ printk("pcap_user_init : pcap_open_live failed - '%s'\n",
-+ errors);
-+ return;
-+ }
-+
-+ pri->dev = dev;
-+ pri->pcap = p;
-+}
-+
-+static int pcap_open(void *data)
-+{
-+ struct pcap_data *pri = data;
-+ __u32 netmask;
-+ int err;
-+
-+ if(pri->pcap == NULL)
-+ return(-ENODEV);
-+
-+ if(pri->filter != NULL){
-+ err = dev_netmask(pri->dev, &netmask);
-+ if(err < 0){
-+ printk("pcap_open : dev_netmask failed\n");
-+ return(-EIO);
-+ }
-+
-+ pri->compiled = um_kmalloc(sizeof(struct bpf_program));
-+ if(pri->compiled == NULL){
-+ printk("pcap_open : kmalloc failed\n");
-+ return(-ENOMEM);
-+ }
-+
-+ err = pcap_compile(pri->pcap,
-+ (struct bpf_program *) pri->compiled,
-+ pri->filter, pri->optimize, netmask);
-+ if(err < 0){
-+ printk("pcap_open : pcap_compile failed - '%s'\n",
-+ pcap_geterr(pri->pcap));
-+ return(-EIO);
-+ }
-+
-+ err = pcap_setfilter(pri->pcap, pri->compiled);
-+ if(err < 0){
-+ printk("pcap_open : pcap_setfilter failed - '%s'\n",
-+ pcap_geterr(pri->pcap));
-+ return(-EIO);
-+ }
-+ }
-+
-+ return(PCAP_FD(pri->pcap));
-+}
-+
-+static void pcap_remove(void *data)
-+{
-+ struct pcap_data *pri = data;
-+
-+ if(pri->compiled != NULL)
-+ pcap_freecode(pri->compiled);
-+
-+ pcap_close(pri->pcap);
-+}
-+
-+struct pcap_handler_data {
-+ char *buffer;
-+ int len;
-+};
-+
-+static void handler(u_char *data, const struct pcap_pkthdr *header,
-+ const u_char *packet)
-+{
-+ int len;
-+
-+ struct pcap_handler_data *hdata = (struct pcap_handler_data *) data;
-+
-+ len = hdata->len < header->caplen ? hdata->len : header->caplen;
-+ memcpy(hdata->buffer, packet, len);
-+ hdata->len = len;
-+}
-+
-+int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri)
-+{
-+ struct pcap_handler_data hdata = ((struct pcap_handler_data)
-+ { .buffer = buffer,
-+ .len = len });
-+ int n;
-+
-+ n = pcap_dispatch(pri->pcap, 1, handler, (u_char *) &hdata);
-+ if(n < 0){
-+ printk("pcap_dispatch failed - %s\n", pcap_geterr(pri->pcap));
-+ return(-EIO);
-+ }
-+ else if(n == 0)
-+ return(0);
-+ return(hdata.len);
-+}
-+
-+struct net_user_info pcap_user_info = {
-+ .init = pcap_user_init,
-+ .open = pcap_open,
-+ .close = NULL,
-+ .remove = pcap_remove,
-+ .set_mtu = NULL,
-+ .add_address = NULL,
-+ .delete_address = NULL,
-+ .max_packet = MAX_PACKET - ETH_HEADER_OTHER
-+};
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/pcap_user.h um/arch/um/drivers/pcap_user.h
---- orig/arch/um/drivers/pcap_user.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/pcap_user.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,31 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "net_user.h"
-+
-+struct pcap_data {
-+ char *host_if;
-+ int promisc;
-+ int optimize;
-+ char *filter;
-+ void *compiled;
-+ void *pcap;
-+ void *dev;
-+};
-+
-+extern struct net_user_info pcap_user_info;
-+
-+extern int pcap_user_read(int fd, void *buf, int len, struct pcap_data *pri);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/port.h um/arch/um/drivers/port.h
---- orig/arch/um/drivers/port.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/port.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,30 @@
-+/*
-+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __PORT_H__
-+#define __PORT_H__
-+
-+extern void *port_data(int port);
-+extern int port_wait(void *data);
-+extern void port_kern_close(void *d);
-+extern int port_connection(int fd, int *socket_out, int *pid_out);
-+extern int port_listen_fd(int port);
-+extern void port_read(int fd, void *data);
-+extern void port_kern_free(void *d);
-+extern int port_rcv_fd(int fd);
-+extern void port_remove_dev(void *d);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/port_kern.c um/arch/um/drivers/port_kern.c
---- orig/arch/um/drivers/port_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/port_kern.c 2004-01-10 06:18:49.000000000 -0500
-@@ -0,0 +1,303 @@
-+/*
-+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/list.h"
-+#include "linux/sched.h"
-+#include "linux/slab.h"
-+#include "linux/irq.h"
-+#include "linux/spinlock.h"
-+#include "linux/errno.h"
-+#include "asm/semaphore.h"
-+#include "asm/errno.h"
-+#include "kern_util.h"
-+#include "kern.h"
-+#include "irq_user.h"
-+#include "irq_kern.h"
-+#include "port.h"
-+#include "init.h"
-+#include "os.h"
-+
-+struct port_list {
-+ struct list_head list;
-+ int has_connection;
-+ struct semaphore sem;
-+ int port;
-+ int fd;
-+ spinlock_t lock;
-+ struct list_head pending;
-+ struct list_head connections;
-+};
-+
-+struct port_dev {
-+ struct port_list *port;
-+ int helper_pid;
-+ int telnetd_pid;
-+};
-+
-+struct connection {
-+ struct list_head list;
-+ int fd;
-+ int helper_pid;
-+ int socket[2];
-+ int telnetd_pid;
-+ struct port_list *port;
-+};
-+
-+static void pipe_interrupt(int irq, void *data, struct pt_regs *regs)
-+{
-+ struct connection *conn = data;
-+ int fd;
-+
-+ fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
-+ if(fd < 0){
-+ if(fd == -EAGAIN)
-+ return;
-+
-+ printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n",
-+ -fd);
-+ os_close_file(conn->fd);
-+ }
-+
-+ list_del(&conn->list);
-+
-+ conn->fd = fd;
-+ list_add(&conn->list, &conn->port->connections);
-+
-+ up(&conn->port->sem);
-+}
-+
-+static int port_accept(struct port_list *port)
-+{
-+ struct connection *conn;
-+ int fd, socket[2], pid, ret = 0;
-+
-+ fd = port_connection(port->fd, socket, &pid);
-+ if(fd < 0){
-+ if(fd != -EAGAIN)
-+ printk(KERN_ERR "port_accept : port_connection "
-+ "returned %d\n", -fd);
-+ goto out;
-+ }
-+
-+ conn = kmalloc(sizeof(*conn), GFP_ATOMIC);
-+ if(conn == NULL){
-+ printk(KERN_ERR "port_accept : failed to allocate "
-+ "connection\n");
-+ goto out_close;
-+ }
-+ *conn = ((struct connection)
-+ { .list = LIST_HEAD_INIT(conn->list),
-+ .fd = fd,
-+ .socket = { socket[0], socket[1] },
-+ .telnetd_pid = pid,
-+ .port = port });
-+
-+ if(um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt,
-+ SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
-+ "telnetd", conn)){
-+ printk(KERN_ERR "port_accept : failed to get IRQ for "
-+ "telnetd\n");
-+ goto out_free;
-+ }
-+
-+ list_add(&conn->list, &port->pending);
-+ return(1);
-+
-+ out_free:
-+ kfree(conn);
-+ out_close:
-+ os_close_file(fd);
-+ if(pid != -1)
-+ os_kill_process(pid, 1);
-+ out:
-+ return(ret);
-+}
-+
-+DECLARE_MUTEX(ports_sem);
-+struct list_head ports = LIST_HEAD_INIT(ports);
-+
-+void port_task_proc(void *unused)
-+{
-+ struct port_list *port;
-+ struct list_head *ele;
-+ unsigned long flags;
-+
-+ save_flags(flags);
-+ list_for_each(ele, &ports){
-+ port = list_entry(ele, struct port_list, list);
-+ if(!port->has_connection)
-+ continue;
-+ reactivate_fd(port->fd, ACCEPT_IRQ);
-+ while(port_accept(port)) ;
-+ port->has_connection = 0;
-+ }
-+ restore_flags(flags);
-+}
-+
-+struct tq_struct port_task = {
-+ .routine = port_task_proc,
-+ .data = NULL
-+};
-+
-+static void port_interrupt(int irq, void *data, struct pt_regs *regs)
-+{
-+ struct port_list *port = data;
-+
-+ port->has_connection = 1;
-+ schedule_task(&port_task);
-+}
-+
-+void *port_data(int port_num)
-+{
-+ struct list_head *ele;
-+ struct port_list *port;
-+ struct port_dev *dev = NULL;
-+ int fd;
-+
-+ down(&ports_sem);
-+ list_for_each(ele, &ports){
-+ port = list_entry(ele, struct port_list, list);
-+ if(port->port == port_num) goto found;
-+ }
-+ port = kmalloc(sizeof(struct port_list), GFP_KERNEL);
-+ if(port == NULL){
-+ printk(KERN_ERR "Allocation of port list failed\n");
-+ goto out;
-+ }
-+
-+ fd = port_listen_fd(port_num);
-+ if(fd < 0){
-+ printk(KERN_ERR "binding to port %d failed, errno = %d\n",
-+ port_num, -fd);
-+ goto out_free;
-+ }
-+ if(um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt,
-+ SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, "port",
-+ port)){
-+ printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num);
-+ goto out_close;
-+ }
-+
-+ *port = ((struct port_list)
-+ { .list = LIST_HEAD_INIT(port->list),
-+ .has_connection = 0,
-+ .sem = __SEMAPHORE_INITIALIZER(port->sem,
-+ 0),
-+ .lock = SPIN_LOCK_UNLOCKED,
-+ .port = port_num,
-+ .fd = fd,
-+ .pending = LIST_HEAD_INIT(port->pending),
-+ .connections = LIST_HEAD_INIT(port->connections) });
-+ list_add(&port->list, &ports);
-+
-+ found:
-+ dev = kmalloc(sizeof(struct port_dev), GFP_KERNEL);
-+ if(dev == NULL){
-+ printk(KERN_ERR "Allocation of port device entry failed\n");
-+ goto out;
-+ }
-+
-+ *dev = ((struct port_dev) { .port = port,
-+ .helper_pid = -1,
-+ .telnetd_pid = -1 });
-+ goto out;
-+
-+ out_free:
-+ kfree(port);
-+ out_close:
-+ os_close_file(fd);
-+ out:
-+ up(&ports_sem);
-+ return(dev);
-+}
-+
-+int port_wait(void *data)
-+{
-+ struct port_dev *dev = data;
-+ struct connection *conn;
-+ struct port_list *port = dev->port;
-+ int fd;
-+
-+ while(1){
-+ if(down_interruptible(&port->sem))
-+ return(-ERESTARTSYS);
-+
-+ spin_lock(&port->lock);
-+
-+ conn = list_entry(port->connections.next, struct connection,
-+ list);
-+ list_del(&conn->list);
-+ spin_unlock(&port->lock);
-+
-+ os_shutdown_socket(conn->socket[0], 1, 1);
-+ os_close_file(conn->socket[0]);
-+ os_shutdown_socket(conn->socket[1], 1, 1);
-+ os_close_file(conn->socket[1]);
-+
-+ /* This is done here because freeing an IRQ can't be done
-+ * within the IRQ handler. So, pipe_interrupt always ups
-+ * the semaphore regardless of whether it got a successful
-+ * connection. Then we loop here throwing out failed
-+ * connections until a good one is found.
-+ */
-+ free_irq(TELNETD_IRQ, conn);
-+
-+ if(conn->fd >= 0) break;
-+ os_close_file(conn->fd);
-+ kfree(conn);
-+ }
-+
-+ fd = conn->fd;
-+ dev->helper_pid = conn->helper_pid;
-+ dev->telnetd_pid = conn->telnetd_pid;
-+ kfree(conn);
-+
-+ return(fd);
-+}
-+
-+void port_remove_dev(void *d)
-+{
-+ struct port_dev *dev = d;
-+
-+ if(dev->helper_pid != -1)
-+ os_kill_process(dev->helper_pid, 0);
-+ if(dev->telnetd_pid != -1)
-+ os_kill_process(dev->telnetd_pid, 1);
-+ dev->helper_pid = -1;
-+ dev->telnetd_pid = -1;
-+}
-+
-+void port_kern_free(void *d)
-+{
-+ struct port_dev *dev = d;
-+
-+ port_remove_dev(dev);
-+ kfree(dev);
-+}
-+
-+static void free_port(void)
-+{
-+ struct list_head *ele;
-+ struct port_list *port;
-+
-+ list_for_each(ele, &ports){
-+ port = list_entry(ele, struct port_list, list);
-+ free_irq_by_fd(port->fd);
-+ os_close_file(port->fd);
-+ }
-+}
-+
-+__uml_exitcall(free_port);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/port_user.c um/arch/um/drivers/port_user.c
---- orig/arch/um/drivers/port_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/port_user.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,213 @@
-+/*
-+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdio.h>
-+#include <stddef.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <errno.h>
-+#include <unistd.h>
-+#include <termios.h>
-+#include <sys/socket.h>
-+#include <sys/un.h>
-+#include <netinet/in.h>
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "user.h"
-+#include "chan_user.h"
-+#include "port.h"
-+#include "helper.h"
-+#include "os.h"
-+
-+struct port_chan {
-+ int raw;
-+ struct termios tt;
-+ void *kernel_data;
-+ char dev[sizeof("32768\0")];
-+};
-+
-+void *port_init(char *str, int device, struct chan_opts *opts)
-+{
-+ struct port_chan *data;
-+ void *kern_data;
-+ char *end;
-+ int port;
-+
-+ if(*str != ':'){
-+ printk("port_init : channel type 'port' must specify a "
-+ "port number\n");
-+ return(NULL);
-+ }
-+ str++;
-+ port = strtoul(str, &end, 0);
-+ if((*end != '\0') || (end == str)){
-+ printk("port_init : couldn't parse port '%s'\n", str);
-+ return(NULL);
-+ }
-+
-+ kern_data = port_data(port);
-+ if(kern_data == NULL)
-+ return(NULL);
-+
-+ data = um_kmalloc(sizeof(*data));
-+ if(data == NULL)
-+ goto err;
-+
-+ *data = ((struct port_chan) { .raw = opts->raw,
-+ .kernel_data = kern_data });
-+ sprintf(data->dev, "%d", port);
-+
-+ return(data);
-+ err:
-+ port_kern_free(kern_data);
-+ return(NULL);
-+}
-+
-+void port_free(void *d)
-+{
-+ struct port_chan *data = d;
-+
-+ port_kern_free(data->kernel_data);
-+ kfree(data);
-+}
-+
-+int port_open(int input, int output, int primary, void *d, char **dev_out)
-+{
-+ struct port_chan *data = d;
-+ int fd;
-+
-+ fd = port_wait(data->kernel_data);
-+ if((fd >= 0) && data->raw){
-+ tcgetattr(fd, &data->tt);
-+ raw(fd, 0);
-+ }
-+ *dev_out = data->dev;
-+ return(fd);
-+}
-+
-+void port_close(int fd, void *d)
-+{
-+ struct port_chan *data = d;
-+
-+ port_remove_dev(data->kernel_data);
-+ os_close_file(fd);
-+}
-+
-+int port_console_write(int fd, const char *buf, int n, void *d)
-+{
-+ struct port_chan *data = d;
-+
-+ return(generic_console_write(fd, buf, n, &data->tt));
-+}
-+
-+struct chan_ops port_ops = {
-+ .type = "port",
-+ .init = port_init,
-+ .open = port_open,
-+ .close = port_close,
-+ .read = generic_read,
-+ .write = generic_write,
-+ .console_write = port_console_write,
-+ .window_size = generic_window_size,
-+ .free = port_free,
-+ .winch = 1,
-+};
-+
-+int port_listen_fd(int port)
-+{
-+ struct sockaddr_in addr;
-+ int fd, err;
-+
-+ fd = socket(PF_INET, SOCK_STREAM, 0);
-+ if(fd == -1)
-+ return(-errno);
-+
-+ addr.sin_family = AF_INET;
-+ addr.sin_port = htons(port);
-+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
-+ if(bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0){
-+ err = -errno;
-+ goto out;
-+ }
-+
-+ if(listen(fd, 1) < 0){
-+ err = -errno;
-+ goto out;
-+ }
-+
-+ err = os_set_fd_block(fd, 0);
-+ if(err < 0)
-+ goto out;
-+
-+ return(fd);
-+ out:
-+ os_close_file(fd);
-+ return(err);
-+}
-+
-+struct port_pre_exec_data {
-+ int sock_fd;
-+ int pipe_fd;
-+};
-+
-+void port_pre_exec(void *arg)
-+{
-+ struct port_pre_exec_data *data = arg;
-+
-+ dup2(data->sock_fd, 0);
-+ dup2(data->sock_fd, 1);
-+ dup2(data->sock_fd, 2);
-+ os_close_file(data->sock_fd);
-+ dup2(data->pipe_fd, 3);
-+ os_shutdown_socket(3, 1, 0);
-+ os_close_file(data->pipe_fd);
-+}
-+
-+int port_connection(int fd, int *socket, int *pid_out)
-+{
-+ int new, err;
-+ char *argv[] = { "/usr/sbin/in.telnetd", "-L",
-+ "/usr/lib/uml/port-helper", NULL };
-+ struct port_pre_exec_data data;
-+
-+ new = os_accept_connection(fd);
-+ if(new < 0)
-+ return(new);
-+
-+ err = os_pipe(socket, 0, 0);
-+ if(err < 0)
-+ goto out_close;
-+
-+ data = ((struct port_pre_exec_data)
-+ { .sock_fd = new,
-+ .pipe_fd = socket[1] });
-+
-+ err = run_helper(port_pre_exec, &data, argv, NULL);
-+ if(err < 0)
-+ goto out_shutdown;
-+
-+ *pid_out = err;
-+ return(new);
-+
-+ out_shutdown:
-+ os_shutdown_socket(socket[0], 1, 1);
-+ os_close_file(socket[0]);
-+ os_shutdown_socket(socket[1], 1, 1);
-+ os_close_file(socket[1]);
-+ out_close:
-+ os_close_file(new);
-+ return(err);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/pty.c um/arch/um/drivers/pty.c
---- orig/arch/um/drivers/pty.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/pty.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,148 @@
-+/*
-+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdio.h>
-+#include <unistd.h>
-+#include <string.h>
-+#include <errno.h>
-+#include <termios.h>
-+#include "chan_user.h"
-+#include "user.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "os.h"
-+
-+struct pty_chan {
-+ void (*announce)(char *dev_name, int dev);
-+ int dev;
-+ int raw;
-+ struct termios tt;
-+ char dev_name[sizeof("/dev/pts/0123456\0")];
-+};
-+
-+void *pty_chan_init(char *str, int device, struct chan_opts *opts)
-+{
-+ struct pty_chan *data;
-+
-+ data = um_kmalloc(sizeof(*data));
-+ if(data == NULL) return(NULL);
-+ *data = ((struct pty_chan) { .announce = opts->announce,
-+ .dev = device,
-+ .raw = opts->raw });
-+ return(data);
-+}
-+
-+int pts_open(int input, int output, int primary, void *d, char **dev_out)
-+{
-+ struct pty_chan *data = d;
-+ char *dev;
-+ int fd;
-+
-+ fd = get_pty();
-+ if(fd < 0){
-+ printk("open_pts : Failed to open pts\n");
-+ return(-errno);
-+ }
-+ if(data->raw){
-+ tcgetattr(fd, &data->tt);
-+ raw(fd, 0);
-+ }
-+
-+ dev = ptsname(fd);
-+ sprintf(data->dev_name, "%s", dev);
-+ *dev_out = data->dev_name;
-+ if(data->announce) (*data->announce)(dev, data->dev);
-+ return(fd);
-+}
-+
-+int getmaster(char *line)
-+{
-+ char *pty, *bank, *cp;
-+ int master, err;
-+
-+ pty = &line[strlen("/dev/ptyp")];
-+ for (bank = "pqrs"; *bank; bank++) {
-+ line[strlen("/dev/pty")] = *bank;
-+ *pty = '0';
-+ if (os_stat_file(line, NULL) < 0)
-+ break;
-+ for (cp = "0123456789abcdef"; *cp; cp++) {
-+ *pty = *cp;
-+ master = os_open_file(line, of_rdwr(OPENFLAGS()), 0);
-+ if (master >= 0) {
-+ char *tp = &line[strlen("/dev/")];
-+
-+ /* verify slave side is usable */
-+ *tp = 't';
-+ err = os_access(line, OS_ACC_RW_OK);
-+ *tp = 'p';
-+ if(err == 0) return(master);
-+ (void) os_close_file(master);
-+ }
-+ }
-+ }
-+ return(-1);
-+}
-+
-+int pty_open(int input, int output, int primary, void *d, char **dev_out)
-+{
-+ struct pty_chan *data = d;
-+ int fd;
-+ char dev[sizeof("/dev/ptyxx\0")] = "/dev/ptyxx";
-+
-+ fd = getmaster(dev);
-+ if(fd < 0) return(-errno);
-+
-+ if(data->raw) raw(fd, 0);
-+ if(data->announce) (*data->announce)(dev, data->dev);
-+
-+ sprintf(data->dev_name, "%s", dev);
-+ *dev_out = data->dev_name;
-+ return(fd);
-+}
-+
-+int pty_console_write(int fd, const char *buf, int n, void *d)
-+{
-+ struct pty_chan *data = d;
-+
-+ return(generic_console_write(fd, buf, n, &data->tt));
-+}
-+
-+struct chan_ops pty_ops = {
-+ .type = "pty",
-+ .init = pty_chan_init,
-+ .open = pty_open,
-+ .close = generic_close,
-+ .read = generic_read,
-+ .write = generic_write,
-+ .console_write = pty_console_write,
-+ .window_size = generic_window_size,
-+ .free = generic_free,
-+ .winch = 0,
-+};
-+
-+struct chan_ops pts_ops = {
-+ .type = "pts",
-+ .init = pty_chan_init,
-+ .open = pts_open,
-+ .close = generic_close,
-+ .read = generic_read,
-+ .write = generic_write,
-+ .console_write = pty_console_write,
-+ .window_size = generic_window_size,
-+ .free = generic_free,
-+ .winch = 0,
-+};
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/slip.h um/arch/um/drivers/slip.h
---- orig/arch/um/drivers/slip.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/slip.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,39 @@
-+#ifndef __UM_SLIP_H
-+#define __UM_SLIP_H
-+
-+#define BUF_SIZE 1500
-+ /* two bytes each for a (pathological) max packet of escaped chars + *
-+ * terminating END char + initial END char */
-+#define ENC_BUF_SIZE (2 * BUF_SIZE + 2)
-+
-+struct slip_data {
-+ void *dev;
-+ char name[sizeof("slnnnnn\0")];
-+ char *addr;
-+ char *gate_addr;
-+ int slave;
-+ char ibuf[ENC_BUF_SIZE];
-+ char obuf[ENC_BUF_SIZE];
-+ int more; /* more data: do not read fd until ibuf has been drained */
-+ int pos;
-+ int esc;
-+};
-+
-+extern struct net_user_info slip_user_info;
-+
-+extern int set_umn_addr(int fd, char *addr, char *ptp_addr);
-+extern int slip_user_read(int fd, void *buf, int len, struct slip_data *pri);
-+extern int slip_user_write(int fd, void *buf, int len, struct slip_data *pri);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/slip_kern.c um/arch/um/drivers/slip_kern.c
---- orig/arch/um/drivers/slip_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/slip_kern.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,109 @@
-+#include "linux/config.h"
-+#include "linux/kernel.h"
-+#include "linux/stddef.h"
-+#include "linux/init.h"
-+#include "linux/netdevice.h"
-+#include "linux/if_arp.h"
-+#include "net_kern.h"
-+#include "net_user.h"
-+#include "kern.h"
-+#include "slip.h"
-+
-+struct slip_init {
-+ char *gate_addr;
-+};
-+
-+void slip_init(struct net_device *dev, void *data)
-+{
-+ struct uml_net_private *private;
-+ struct slip_data *spri;
-+ struct slip_init *init = data;
-+
-+ private = dev->priv;
-+ spri = (struct slip_data *) private->user;
-+ *spri = ((struct slip_data)
-+ { .name = { '\0' },
-+ .addr = NULL,
-+ .gate_addr = init->gate_addr,
-+ .slave = -1,
-+ .ibuf = { '\0' },
-+ .obuf = { '\0' },
-+ .pos = 0,
-+ .esc = 0,
-+ .dev = dev });
-+
-+ dev->init = NULL;
-+ dev->hard_header_len = 0;
-+ dev->addr_len = 4;
-+ dev->type = ARPHRD_ETHER;
-+ dev->tx_queue_len = 256;
-+ dev->flags = IFF_NOARP;
-+ printk("SLIP backend - SLIP IP = %s\n", spri->gate_addr);
-+}
-+
-+static unsigned short slip_protocol(struct sk_buff *skbuff)
-+{
-+ return(htons(ETH_P_IP));
-+}
-+
-+static int slip_read(int fd, struct sk_buff **skb,
-+ struct uml_net_private *lp)
-+{
-+ return(slip_user_read(fd, (*skb)->mac.raw, (*skb)->dev->mtu,
-+ (struct slip_data *) &lp->user));
-+}
-+
-+static int slip_write(int fd, struct sk_buff **skb,
-+ struct uml_net_private *lp)
-+{
-+ return(slip_user_write(fd, (*skb)->data, (*skb)->len,
-+ (struct slip_data *) &lp->user));
-+}
-+
-+struct net_kern_info slip_kern_info = {
-+ .init = slip_init,
-+ .protocol = slip_protocol,
-+ .read = slip_read,
-+ .write = slip_write,
-+};
-+
-+static int slip_setup(char *str, char **mac_out, void *data)
-+{
-+ struct slip_init *init = data;
-+
-+ *init = ((struct slip_init)
-+ { .gate_addr = NULL });
-+
-+ if(str[0] != '\0')
-+ init->gate_addr = str;
-+ return(1);
-+}
-+
-+static struct transport slip_transport = {
-+ .list = LIST_HEAD_INIT(slip_transport.list),
-+ .name = "slip",
-+ .setup = slip_setup,
-+ .user = &slip_user_info,
-+ .kern = &slip_kern_info,
-+ .private_size = sizeof(struct slip_data),
-+ .setup_size = sizeof(struct slip_init),
-+};
-+
-+static int register_slip(void)
-+{
-+ register_transport(&slip_transport);
-+ return(1);
-+}
-+
-+__initcall(register_slip);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/slip_proto.h um/arch/um/drivers/slip_proto.h
---- orig/arch/um/drivers/slip_proto.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/slip_proto.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,93 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UM_SLIP_PROTO_H__
-+#define __UM_SLIP_PROTO_H__
-+
-+/* SLIP protocol characters. */
-+#define SLIP_END 0300 /* indicates end of frame */
-+#define SLIP_ESC 0333 /* indicates byte stuffing */
-+#define SLIP_ESC_END 0334 /* ESC ESC_END means END 'data' */
-+#define SLIP_ESC_ESC 0335 /* ESC ESC_ESC means ESC 'data' */
-+
-+static inline int slip_unesc(unsigned char c,char *buf,int *pos, int *esc)
-+{
-+ int ret;
-+
-+ switch(c){
-+ case SLIP_END:
-+ *esc = 0;
-+ ret=*pos;
-+ *pos=0;
-+ return(ret);
-+ case SLIP_ESC:
-+ *esc = 1;
-+ return(0);
-+ case SLIP_ESC_ESC:
-+ if(*esc){
-+ *esc = 0;
-+ c = SLIP_ESC;
-+ }
-+ break;
-+ case SLIP_ESC_END:
-+ if(*esc){
-+ *esc = 0;
-+ c = SLIP_END;
-+ }
-+ break;
-+ }
-+ buf[(*pos)++] = c;
-+ return(0);
-+}
-+
-+static inline int slip_esc(unsigned char *s, unsigned char *d, int len)
-+{
-+ unsigned char *ptr = d;
-+ unsigned char c;
-+
-+ /*
-+ * Send an initial END character to flush out any
-+ * data that may have accumulated in the receiver
-+ * due to line noise.
-+ */
-+
-+ *ptr++ = SLIP_END;
-+
-+ /*
-+ * For each byte in the packet, send the appropriate
-+ * character sequence, according to the SLIP protocol.
-+ */
-+
-+ while (len-- > 0) {
-+ switch(c = *s++) {
-+ case SLIP_END:
-+ *ptr++ = SLIP_ESC;
-+ *ptr++ = SLIP_ESC_END;
-+ break;
-+ case SLIP_ESC:
-+ *ptr++ = SLIP_ESC;
-+ *ptr++ = SLIP_ESC_ESC;
-+ break;
-+ default:
-+ *ptr++ = c;
-+ break;
-+ }
-+ }
-+ *ptr++ = SLIP_END;
-+ return (ptr - d);
-+}
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/slip_user.c um/arch/um/drivers/slip_user.c
---- orig/arch/um/drivers/slip_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/slip_user.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,274 @@
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <stddef.h>
-+#include <sched.h>
-+#include <string.h>
-+#include <sys/errno.h>
-+#include <sys/termios.h>
-+#include <sys/wait.h>
-+#include <sys/signal.h>
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "user.h"
-+#include "net_user.h"
-+#include "slip.h"
-+#include "slip_proto.h"
-+#include "helper.h"
-+#include "os.h"
-+
-+void slip_user_init(void *data, void *dev)
-+{
-+ struct slip_data *pri = data;
-+
-+ pri->dev = dev;
-+}
-+
-+static int set_up_tty(int fd)
-+{
-+ int i;
-+ struct termios tios;
-+
-+ if (tcgetattr(fd, &tios) < 0) {
-+ printk("could not get initial terminal attributes\n");
-+ return(-1);
-+ }
-+
-+ tios.c_cflag = CS8 | CREAD | HUPCL | CLOCAL;
-+ tios.c_iflag = IGNBRK | IGNPAR;
-+ tios.c_oflag = 0;
-+ tios.c_lflag = 0;
-+ for (i = 0; i < NCCS; i++)
-+ tios.c_cc[i] = 0;
-+ tios.c_cc[VMIN] = 1;
-+ tios.c_cc[VTIME] = 0;
-+
-+ cfsetospeed(&tios, B38400);
-+ cfsetispeed(&tios, B38400);
-+
-+ if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
-+ printk("failed to set terminal attributes\n");
-+ return(-1);
-+ }
-+ return(0);
-+}
-+
-+struct slip_pre_exec_data {
-+ int stdin;
-+ int stdout;
-+ int close_me;
-+};
-+
-+static void slip_pre_exec(void *arg)
-+{
-+ struct slip_pre_exec_data *data = arg;
-+
-+ if(data->stdin >= 0) dup2(data->stdin, 0);
-+ dup2(data->stdout, 1);
-+ if(data->close_me >= 0) os_close_file(data->close_me);
-+}
-+
-+static int slip_tramp(char **argv, int fd)
-+{
-+ struct slip_pre_exec_data pe_data;
-+ char *output;
-+ int status, pid, fds[2], err, output_len;
-+
-+ err = os_pipe(fds, 1, 0);
-+ if(err < 0){
-+ printk("slip_tramp : pipe failed, err = %d\n", -err);
-+ return(err);
-+ }
-+
-+ err = 0;
-+ pe_data.stdin = fd;
-+ pe_data.stdout = fds[1];
-+ pe_data.close_me = fds[0];
-+ pid = run_helper(slip_pre_exec, &pe_data, argv, NULL);
-+
-+ if(pid < 0) err = pid;
-+ else {
-+ output_len = page_size();
-+ output = um_kmalloc(output_len);
-+ if(output == NULL)
-+ printk("slip_tramp : failed to allocate output "
-+ "buffer\n");
-+
-+ os_close_file(fds[1]);
-+ read_output(fds[0], output, output_len);
-+ if(output != NULL){
-+ printk("%s", output);
-+ kfree(output);
-+ }
-+ if(waitpid(pid, &status, 0) < 0) err = errno;
-+ else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)){
-+ printk("'%s' didn't exit with status 0\n", argv[0]);
-+ err = -EINVAL;
-+ }
-+ }
-+ return(err);
-+}
-+
-+static int slip_open(void *data)
-+{
-+ struct slip_data *pri = data;
-+ char version_buf[sizeof("nnnnn\0")];
-+ char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
-+ char *argv[] = { "uml_net", version_buf, "slip", "up", gate_buf,
-+ NULL };
-+ int sfd, mfd, err;
-+
-+ mfd = get_pty();
-+ if(mfd < 0){
-+ printk("umn : Failed to open pty, err = %d\n", -mfd);
-+ return(mfd);
-+ }
-+ sfd = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0);
-+ if(sfd < 0){
-+ printk("Couldn't open tty for slip line, err = %d\n", -sfd);
-+ return(sfd);
-+ }
-+ if(set_up_tty(sfd)) return(-1);
-+ pri->slave = sfd;
-+ pri->pos = 0;
-+ pri->esc = 0;
-+ if(pri->gate_addr != NULL){
-+ sprintf(version_buf, "%d", UML_NET_VERSION);
-+ strcpy(gate_buf, pri->gate_addr);
-+
-+ err = slip_tramp(argv, sfd);
-+
-+ if(err < 0){
-+ printk("slip_tramp failed - err = %d\n", -err);
-+ return(err);
-+ }
-+ err = os_get_ifname(pri->slave, pri->name);
-+ if(err < 0){
-+ printk("get_ifname failed, err = %d\n", -err);
-+ return(err);
-+ }
-+ iter_addresses(pri->dev, open_addr, pri->name);
-+ }
-+ else {
-+ err = os_set_slip(sfd);
-+ if(err < 0){
-+ printk("Failed to set slip discipline encapsulation - "
-+ "err = %d\n", -err);
-+ return(err);
-+ }
-+ }
-+ return(mfd);
-+}
-+
-+static void slip_close(int fd, void *data)
-+{
-+ struct slip_data *pri = data;
-+ char version_buf[sizeof("nnnnn\0")];
-+ char *argv[] = { "uml_net", version_buf, "slip", "down", pri->name,
-+ NULL };
-+ int err;
-+
-+ if(pri->gate_addr != NULL)
-+ iter_addresses(pri->dev, close_addr, pri->name);
-+
-+ sprintf(version_buf, "%d", UML_NET_VERSION);
-+
-+ err = slip_tramp(argv, -1);
-+
-+ if(err != 0)
-+ printk("slip_tramp failed - errno = %d\n", -err);
-+ os_close_file(fd);
-+ os_close_file(pri->slave);
-+ pri->slave = -1;
-+}
-+
-+int slip_user_read(int fd, void *buf, int len, struct slip_data *pri)
-+{
-+ int i, n, size, start;
-+
-+ if(pri->more>0) {
-+ i = 0;
-+ while(i < pri->more) {
-+ size = slip_unesc(pri->ibuf[i++],
-+ pri->ibuf, &pri->pos, &pri->esc);
-+ if(size){
-+ memcpy(buf, pri->ibuf, size);
-+ memmove(pri->ibuf, &pri->ibuf[i], pri->more-i);
-+ pri->more=pri->more-i;
-+ return(size);
-+ }
-+ }
-+ pri->more=0;
-+ }
-+
-+ n = net_read(fd, &pri->ibuf[pri->pos], sizeof(pri->ibuf) - pri->pos);
-+ if(n <= 0) return(n);
-+
-+ start = pri->pos;
-+ for(i = 0; i < n; i++){
-+ size = slip_unesc(pri->ibuf[start + i],
-+ pri->ibuf, &pri->pos, &pri->esc);
-+ if(size){
-+ memcpy(buf, pri->ibuf, size);
-+ memmove(pri->ibuf, &pri->ibuf[start+i+1], n-(i+1));
-+ pri->more=n-(i+1);
-+ return(size);
-+ }
-+ }
-+ return(0);
-+}
-+
-+int slip_user_write(int fd, void *buf, int len, struct slip_data *pri)
-+{
-+ int actual, n;
-+
-+ actual = slip_esc(buf, pri->obuf, len);
-+ n = net_write(fd, pri->obuf, actual);
-+ if(n < 0) return(n);
-+ else return(len);
-+}
-+
-+static int slip_set_mtu(int mtu, void *data)
-+{
-+ return(mtu);
-+}
-+
-+static void slip_add_addr(unsigned char *addr, unsigned char *netmask,
-+ void *data)
-+{
-+ struct slip_data *pri = data;
-+
-+ if(pri->slave < 0) return;
-+ open_addr(addr, netmask, pri->name);
-+}
-+
-+static void slip_del_addr(unsigned char *addr, unsigned char *netmask,
-+ void *data)
-+{
-+ struct slip_data *pri = data;
-+
-+ if(pri->slave < 0) return;
-+ close_addr(addr, netmask, pri->name);
-+}
-+
-+struct net_user_info slip_user_info = {
-+ .init = slip_user_init,
-+ .open = slip_open,
-+ .close = slip_close,
-+ .remove = NULL,
-+ .set_mtu = slip_set_mtu,
-+ .add_address = slip_add_addr,
-+ .delete_address = slip_del_addr,
-+ .max_packet = BUF_SIZE
-+};
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/slirp.h um/arch/um/drivers/slirp.h
---- orig/arch/um/drivers/slirp.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/slirp.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,51 @@
-+#ifndef __UM_SLIRP_H
-+#define __UM_SLIRP_H
-+
-+#define BUF_SIZE 1500
-+ /* two bytes each for a (pathological) max packet of escaped chars + *
-+ * terminating END char + initial END char */
-+#define ENC_BUF_SIZE (2 * BUF_SIZE + 2)
-+
-+#define SLIRP_MAX_ARGS 100
-+/*
-+ * XXX this next definition is here because I don't understand why this
-+ * initializer doesn't work in slirp_kern.c:
-+ *
-+ * argv : { init->argv[ 0 ... SLIRP_MAX_ARGS-1 ] },
-+ *
-+ * or why I can't typecast like this:
-+ *
-+ * argv : (char* [SLIRP_MAX_ARGS])(init->argv),
-+ */
-+struct arg_list_dummy_wrapper { char *argv[SLIRP_MAX_ARGS]; };
-+
-+struct slirp_data {
-+ void *dev;
-+ struct arg_list_dummy_wrapper argw;
-+ int pid;
-+ int slave;
-+ char ibuf[ENC_BUF_SIZE];
-+ char obuf[ENC_BUF_SIZE];
-+ int more; /* more data: do not read fd until ibuf has been drained */
-+ int pos;
-+ int esc;
-+};
-+
-+extern struct net_user_info slirp_user_info;
-+
-+extern int set_umn_addr(int fd, char *addr, char *ptp_addr);
-+extern int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri);
-+extern int slirp_user_write(int fd, void *buf, int len, struct slirp_data *pri);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/slirp_kern.c um/arch/um/drivers/slirp_kern.c
---- orig/arch/um/drivers/slirp_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/slirp_kern.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,132 @@
-+#include "linux/kernel.h"
-+#include "linux/stddef.h"
-+#include "linux/init.h"
-+#include "linux/netdevice.h"
-+#include "linux/if_arp.h"
-+#include "net_kern.h"
-+#include "net_user.h"
-+#include "kern.h"
-+#include "slirp.h"
-+
-+struct slirp_init {
-+ struct arg_list_dummy_wrapper argw; /* XXX should be simpler... */
-+};
-+
-+void slirp_init(struct net_device *dev, void *data)
-+{
-+ struct uml_net_private *private;
-+ struct slirp_data *spri;
-+ struct slirp_init *init = data;
-+ int i;
-+
-+ private = dev->priv;
-+ spri = (struct slirp_data *) private->user;
-+ *spri = ((struct slirp_data)
-+ { .argw = init->argw,
-+ .pid = -1,
-+ .slave = -1,
-+ .ibuf = { '\0' },
-+ .obuf = { '\0' },
-+ .pos = 0,
-+ .esc = 0,
-+ .dev = dev });
-+
-+ dev->init = NULL;
-+ dev->hard_header_len = 0;
-+ dev->addr_len = 4;
-+ dev->type = ARPHRD_ETHER;
-+ dev->tx_queue_len = 256;
-+ dev->flags = IFF_NOARP;
-+ printk("SLIRP backend - command line:");
-+ for(i=0;spri->argw.argv[i]!=NULL;i++) {
-+ printk(" '%s'",spri->argw.argv[i]);
-+ }
-+ printk("\n");
-+}
-+
-+static unsigned short slirp_protocol(struct sk_buff *skbuff)
-+{
-+ return(htons(ETH_P_IP));
-+}
-+
-+static int slirp_read(int fd, struct sk_buff **skb,
-+ struct uml_net_private *lp)
-+{
-+ return(slirp_user_read(fd, (*skb)->mac.raw, (*skb)->dev->mtu,
-+ (struct slirp_data *) &lp->user));
-+}
-+
-+static int slirp_write(int fd, struct sk_buff **skb,
-+ struct uml_net_private *lp)
-+{
-+ return(slirp_user_write(fd, (*skb)->data, (*skb)->len,
-+ (struct slirp_data *) &lp->user));
-+}
-+
-+struct net_kern_info slirp_kern_info = {
-+ .init = slirp_init,
-+ .protocol = slirp_protocol,
-+ .read = slirp_read,
-+ .write = slirp_write,
-+};
-+
-+static int slirp_setup(char *str, char **mac_out, void *data)
-+{
-+ struct slirp_init *init = data;
-+ int i=0;
-+
-+ *init = ((struct slirp_init)
-+ { argw : { { "slirp", NULL } } });
-+
-+ str = split_if_spec(str, mac_out, NULL);
-+
-+ if(str == NULL) { /* no command line given after MAC addr */
-+ return(1);
-+ }
-+
-+ do {
-+ if(i>=SLIRP_MAX_ARGS-1) {
-+ printk("slirp_setup: truncating slirp arguments\n");
-+ break;
-+ }
-+ init->argw.argv[i++] = str;
-+ while(*str && *str!=',') {
-+ if(*str=='_') *str=' ';
-+ str++;
-+ }
-+ if(*str!=',')
-+ break;
-+ *str++='\0';
-+ } while(1);
-+ init->argw.argv[i]=NULL;
-+ return(1);
-+}
-+
-+static struct transport slirp_transport = {
-+ .list = LIST_HEAD_INIT(slirp_transport.list),
-+ .name = "slirp",
-+ .setup = slirp_setup,
-+ .user = &slirp_user_info,
-+ .kern = &slirp_kern_info,
-+ .private_size = sizeof(struct slirp_data),
-+ .setup_size = sizeof(struct slirp_init),
-+};
-+
-+static int register_slirp(void)
-+{
-+ register_transport(&slirp_transport);
-+ return(1);
-+}
-+
-+__initcall(register_slirp);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/slirp_user.c um/arch/um/drivers/slirp_user.c
---- orig/arch/um/drivers/slirp_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/slirp_user.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,201 @@
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <stddef.h>
-+#include <sched.h>
-+#include <string.h>
-+#include <sys/errno.h>
-+#include <sys/wait.h>
-+#include <sys/signal.h>
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "user.h"
-+#include "net_user.h"
-+#include "slirp.h"
-+#include "slip_proto.h"
-+#include "helper.h"
-+#include "os.h"
-+
-+void slirp_user_init(void *data, void *dev)
-+{
-+ struct slirp_data *pri = data;
-+
-+ pri->dev = dev;
-+}
-+
-+struct slirp_pre_exec_data {
-+ int stdin;
-+ int stdout;
-+};
-+
-+static void slirp_pre_exec(void *arg)
-+{
-+ struct slirp_pre_exec_data *data = arg;
-+
-+ if(data->stdin != -1) dup2(data->stdin, 0);
-+ if(data->stdout != -1) dup2(data->stdout, 1);
-+}
-+
-+static int slirp_tramp(char **argv, int fd)
-+{
-+ struct slirp_pre_exec_data pe_data;
-+ int pid;
-+
-+ pe_data.stdin = fd;
-+ pe_data.stdout = fd;
-+ pid = run_helper(slirp_pre_exec, &pe_data, argv, NULL);
-+
-+ return(pid);
-+}
-+
-+/* XXX This is just a trivial wrapper around os_pipe */
-+static int slirp_datachan(int *mfd, int *sfd)
-+{
-+ int fds[2], err;
-+
-+ err = os_pipe(fds, 1, 1);
-+ if(err < 0){
-+ printk("slirp_datachan: Failed to open pipe, err = %d\n", -err);
-+ return(err);
-+ }
-+
-+ *mfd = fds[0];
-+ *sfd = fds[1];
-+ return(0);
-+}
-+
-+static int slirp_open(void *data)
-+{
-+ struct slirp_data *pri = data;
-+ int sfd, mfd, pid, err;
-+
-+ err = slirp_datachan(&mfd, &sfd);
-+ if(err)
-+ return(err);
-+
-+ pid = slirp_tramp(pri->argw.argv, sfd);
-+
-+ if(pid < 0){
-+ printk("slirp_tramp failed - errno = %d\n", -pid);
-+ os_close_file(sfd);
-+ os_close_file(mfd);
-+ return(pid);
-+ }
-+
-+ pri->slave = sfd;
-+ pri->pos = 0;
-+ pri->esc = 0;
-+
-+ pri->pid = pid;
-+
-+ return(mfd);
-+}
-+
-+static void slirp_close(int fd, void *data)
-+{
-+ struct slirp_data *pri = data;
-+ int status,err;
-+
-+ os_close_file(fd);
-+ os_close_file(pri->slave);
-+
-+ pri->slave = -1;
-+
-+ if(pri->pid<1) {
-+ printk("slirp_close: no child process to shut down\n");
-+ return;
-+ }
-+
-+#if 0
-+ if(kill(pri->pid, SIGHUP)<0) {
-+ printk("slirp_close: sending hangup to %d failed (%d)\n",
-+ pri->pid, errno);
-+ }
-+#endif
-+
-+ err = waitpid(pri->pid, &status, WNOHANG);
-+ if(err<0) {
-+ printk("slirp_close: waitpid returned %d\n", errno);
-+ return;
-+ }
-+
-+ if(err==0) {
-+ printk("slirp_close: process %d has not exited\n");
-+ return;
-+ }
-+
-+ pri->pid = -1;
-+}
-+
-+int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri)
-+{
-+ int i, n, size, start;
-+
-+ if(pri->more>0) {
-+ i = 0;
-+ while(i < pri->more) {
-+ size = slip_unesc(pri->ibuf[i++],
-+ pri->ibuf,&pri->pos,&pri->esc);
-+ if(size){
-+ memcpy(buf, pri->ibuf, size);
-+ memmove(pri->ibuf, &pri->ibuf[i], pri->more-i);
-+ pri->more=pri->more-i;
-+ return(size);
-+ }
-+ }
-+ pri->more=0;
-+ }
-+
-+ n = net_read(fd, &pri->ibuf[pri->pos], sizeof(pri->ibuf) - pri->pos);
-+ if(n <= 0) return(n);
-+
-+ start = pri->pos;
-+ for(i = 0; i < n; i++){
-+ size = slip_unesc(pri->ibuf[start + i],
-+ pri->ibuf,&pri->pos,&pri->esc);
-+ if(size){
-+ memcpy(buf, pri->ibuf, size);
-+ memmove(pri->ibuf, &pri->ibuf[start+i+1], n-(i+1));
-+ pri->more=n-(i+1);
-+ return(size);
-+ }
-+ }
-+ return(0);
-+}
-+
-+int slirp_user_write(int fd, void *buf, int len, struct slirp_data *pri)
-+{
-+ int actual, n;
-+
-+ actual = slip_esc(buf, pri->obuf, len);
-+ n = net_write(fd, pri->obuf, actual);
-+ if(n < 0) return(n);
-+ else return(len);
-+}
-+
-+static int slirp_set_mtu(int mtu, void *data)
-+{
-+ return(mtu);
-+}
-+
-+struct net_user_info slirp_user_info = {
-+ .init = slirp_user_init,
-+ .open = slirp_open,
-+ .close = slirp_close,
-+ .remove = NULL,
-+ .set_mtu = slirp_set_mtu,
-+ .add_address = NULL,
-+ .delete_address = NULL,
-+ .max_packet = BUF_SIZE
-+};
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/ssl.c um/arch/um/drivers/ssl.c
---- orig/arch/um/drivers/ssl.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/ssl.c 2004-01-10 06:20:17.000000000 -0500
-@@ -0,0 +1,300 @@
-+/*
-+ * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/config.h"
-+#include "linux/fs.h"
-+#include "linux/tty.h"
-+#include "linux/tty_driver.h"
-+#include "linux/major.h"
-+#include "linux/mm.h"
-+#include "linux/init.h"
-+#include "linux/console.h"
-+#include "asm/termbits.h"
-+#include "asm/irq.h"
-+#include "line.h"
-+#include "ssl.h"
-+#include "chan_kern.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "kern.h"
-+#include "init.h"
-+#include "irq_user.h"
-+#include "mconsole_kern.h"
-+#include "2_5compat.h"
-+
-+static int ssl_version = 1;
-+
-+/* Referenced only by tty_driver below - presumably it's locked correctly
-+ * by the tty driver.
-+ */
-+static int ssl_refcount = 0;
-+
-+static struct tty_driver ssl_driver;
-+
-+#define NR_PORTS 64
-+
-+void ssl_announce(char *dev_name, int dev)
-+{
-+ printk(KERN_INFO "Serial line %d assigned device '%s'\n", dev,
-+ dev_name);
-+}
-+
-+static struct chan_opts opts = {
-+ .announce = ssl_announce,
-+ .xterm_title = "Serial Line #%d",
-+ .raw = 1,
-+ .tramp_stack = 0,
-+ .in_kernel = 1,
-+};
-+
-+static int ssl_config(char *str);
-+static int ssl_get_config(char *dev, char *str, int size, char **error_out);
-+static int ssl_remove(char *str);
-+
-+static struct line_driver driver = {
-+ .name = "UML serial line",
-+ .devfs_name = "tts/%d",
-+ .major = TTY_MAJOR,
-+ .minor_start = 64,
-+ .type = TTY_DRIVER_TYPE_SERIAL,
-+ .subtype = 0,
-+ .read_irq = SSL_IRQ,
-+ .read_irq_name = "ssl",
-+ .write_irq = SSL_WRITE_IRQ,
-+ .write_irq_name = "ssl-write",
-+ .symlink_from = "serial",
-+ .symlink_to = "tts",
-+ .mc = {
-+ .name = "ssl",
-+ .config = ssl_config,
-+ .get_config = ssl_get_config,
-+ .remove = ssl_remove,
-+ },
-+};
-+
-+/* The array is initialized by line_init, which is an initcall. The
-+ * individual elements are protected by individual semaphores.
-+ */
-+static struct line serial_lines[NR_PORTS] =
-+ { [0 ... NR_PORTS - 1] = LINE_INIT(CONFIG_SSL_CHAN, &driver) };
-+
-+static struct lines lines = LINES_INIT(NR_PORTS);
-+
-+static int ssl_config(char *str)
-+{
-+ return(line_config(serial_lines,
-+ sizeof(serial_lines)/sizeof(serial_lines[0]), str));
-+}
-+
-+static int ssl_get_config(char *dev, char *str, int size, char **error_out)
-+{
-+ return(line_get_config(dev, serial_lines,
-+ sizeof(serial_lines)/sizeof(serial_lines[0]),
-+ str, size, error_out));
-+}
-+
-+static int ssl_remove(char *str)
-+{
-+ return(line_remove(serial_lines,
-+ sizeof(serial_lines)/sizeof(serial_lines[0]), str));
-+}
-+
-+int ssl_open(struct tty_struct *tty, struct file *filp)
-+{
-+ return(line_open(serial_lines, tty, &opts));
-+}
-+
-+static void ssl_close(struct tty_struct *tty, struct file * filp)
-+{
-+ line_close(serial_lines, tty);
-+}
-+
-+static int ssl_write(struct tty_struct * tty, int from_user,
-+ const unsigned char *buf, int count)
-+{
-+ return(line_write(serial_lines, tty, from_user, buf, count));
-+}
-+
-+static void ssl_put_char(struct tty_struct *tty, unsigned char ch)
-+{
-+ line_write(serial_lines, tty, 0, &ch, sizeof(ch));
-+}
-+
-+static void ssl_flush_chars(struct tty_struct *tty)
-+{
-+ return;
-+}
-+
-+static int ssl_chars_in_buffer(struct tty_struct *tty)
-+{
-+ return(0);
-+}
-+
-+static void ssl_flush_buffer(struct tty_struct *tty)
-+{
-+ return;
-+}
-+
-+static int ssl_ioctl(struct tty_struct *tty, struct file * file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ int ret;
-+
-+ ret = 0;
-+ switch(cmd){
-+ case TCGETS:
-+ case TCSETS:
-+ case TCFLSH:
-+ case TCSETSF:
-+ case TCSETSW:
-+ case TCGETA:
-+ case TIOCMGET:
-+ case TCSBRK:
-+ case TCSBRKP:
-+ case TIOCMSET:
-+ ret = -ENOIOCTLCMD;
-+ break;
-+ default:
-+ printk(KERN_ERR
-+ "Unimplemented ioctl in ssl_ioctl : 0x%x\n", cmd);
-+ ret = -ENOIOCTLCMD;
-+ break;
-+ }
-+ return(ret);
-+}
-+
-+static void ssl_throttle(struct tty_struct * tty)
-+{
-+ printk(KERN_ERR "Someone should implement ssl_throttle\n");
-+}
-+
-+static void ssl_unthrottle(struct tty_struct * tty)
-+{
-+ printk(KERN_ERR "Someone should implement ssl_unthrottle\n");
-+}
-+
-+static void ssl_set_termios(struct tty_struct *tty,
-+ struct termios *old_termios)
-+{
-+}
-+
-+static void ssl_stop(struct tty_struct *tty)
-+{
-+ printk(KERN_ERR "Someone should implement ssl_stop\n");
-+}
-+
-+static void ssl_start(struct tty_struct *tty)
-+{
-+ printk(KERN_ERR "Someone should implement ssl_start\n");
-+}
-+
-+void ssl_hangup(struct tty_struct *tty)
-+{
-+}
-+
-+static struct tty_driver ssl_driver = {
-+ .refcount = &ssl_refcount,
-+ .open = ssl_open,
-+ .close = ssl_close,
-+ .write = ssl_write,
-+ .put_char = ssl_put_char,
-+ .flush_chars = ssl_flush_chars,
-+ .chars_in_buffer = ssl_chars_in_buffer,
-+ .flush_buffer = ssl_flush_buffer,
-+ .ioctl = ssl_ioctl,
-+ .throttle = ssl_throttle,
-+ .unthrottle = ssl_unthrottle,
-+ .set_termios = ssl_set_termios,
-+ .stop = ssl_stop,
-+ .start = ssl_start,
-+ .hangup = ssl_hangup
-+};
-+
-+/* Changed by ssl_init and referenced by ssl_exit, which are both serialized
-+ * by being an initcall and exitcall, respectively.
-+ */
-+static int ssl_init_done = 0;
-+
-+static void ssl_console_write(struct console *c, const char *string,
-+ unsigned len)
-+{
-+ struct line *line = &serial_lines[c->index];
-+ if(ssl_init_done)
-+ down(&line->sem);
-+ console_write_chan(&line->chan_list, string, len);
-+ if(ssl_init_done)
-+ up(&line->sem);
-+}
-+
-+static kdev_t ssl_console_device(struct console *c)
-+{
-+ return mk_kdev(TTY_MAJOR, c->index);
-+}
-+
-+static int ssl_console_setup(struct console *co, char *options)
-+{
-+ return(0);
-+}
-+
-+static struct console ssl_cons = {
-+ name: "ttyS",
-+ write: ssl_console_write,
-+ device: ssl_console_device,
-+ setup: ssl_console_setup,
-+ flags: CON_PRINTBUFFER,
-+ index: -1,
-+};
-+
-+int ssl_init(void)
-+{
-+ char *new_title;
-+
-+ printk(KERN_INFO "Initializing software serial port version %d\n",
-+ ssl_version);
-+
-+ line_register_devfs(&lines, &driver, &ssl_driver, serial_lines,
-+ sizeof(serial_lines)/sizeof(serial_lines[0]));
-+
-+ lines_init(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0]));
-+
-+ new_title = add_xterm_umid(opts.xterm_title);
-+ if(new_title != NULL) opts.xterm_title = new_title;
-+
-+ register_console(&ssl_cons);
-+ ssl_init_done = 1;
-+ return(0);
-+}
-+
-+__initcall(ssl_init);
-+
-+static int ssl_chan_setup(char *str)
-+{
-+ return(line_setup(serial_lines,
-+ sizeof(serial_lines)/sizeof(serial_lines[0]),
-+ str, 1));
-+}
-+
-+__setup("ssl", ssl_chan_setup);
-+__channel_help(ssl_chan_setup, "ssl");
-+
-+static void ssl_exit(void)
-+{
-+ if(!ssl_init_done) return;
-+ close_lines(serial_lines,
-+ sizeof(serial_lines)/sizeof(serial_lines[0]));
-+}
-+
-+__uml_exitcall(ssl_exit);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/ssl.h um/arch/um/drivers/ssl.h
---- orig/arch/um/drivers/ssl.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/ssl.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,23 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __SSL_H__
-+#define __SSL_H__
-+
-+extern int ssl_read(int fd, int line);
-+extern void ssl_receive_char(int line, char ch);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/stdio_console.c um/arch/um/drivers/stdio_console.c
---- orig/arch/um/drivers/stdio_console.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/stdio_console.c 2003-11-07 03:03:03.000000000 -0500
-@@ -0,0 +1,258 @@
-+/*
-+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/config.h"
-+#include "linux/posix_types.h"
-+#include "linux/tty.h"
-+#include "linux/tty_flip.h"
-+#include "linux/types.h"
-+#include "linux/major.h"
-+#include "linux/kdev_t.h"
-+#include "linux/console.h"
-+#include "linux/string.h"
-+#include "linux/sched.h"
-+#include "linux/list.h"
-+#include "linux/init.h"
-+#include "linux/interrupt.h"
-+#include "linux/slab.h"
-+#include "asm/current.h"
-+#include "asm/softirq.h"
-+#include "asm/hardirq.h"
-+#include "asm/irq.h"
-+#include "stdio_console.h"
-+#include "line.h"
-+#include "chan_kern.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "irq_user.h"
-+#include "mconsole_kern.h"
-+#include "init.h"
-+#include "2_5compat.h"
-+
-+#define MAX_TTYS (8)
-+
-+/* Referenced only by tty_driver below - presumably it's locked correctly
-+ * by the tty driver.
-+ */
-+
-+static struct tty_driver console_driver;
-+
-+static int console_refcount = 0;
-+
-+static struct chan_ops init_console_ops = {
-+ .type = "you shouldn't see this",
-+ .init = NULL,
-+ .open = NULL,
-+ .close = NULL,
-+ .read = NULL,
-+ .write = NULL,
-+ .console_write = generic_write,
-+ .window_size = NULL,
-+ .free = NULL,
-+ .winch = 0,
-+};
-+
-+static struct chan init_console_chan = {
-+ .list = { },
-+ .primary = 1,
-+ .input = 0,
-+ .output = 1,
-+ .opened = 1,
-+ .fd = 1,
-+ .pri = INIT_STATIC,
-+ .ops = &init_console_ops,
-+ .data = NULL
-+};
-+
-+void stdio_announce(char *dev_name, int dev)
-+{
-+ printk(KERN_INFO "Virtual console %d assigned device '%s'\n", dev,
-+ dev_name);
-+}
-+
-+static struct chan_opts opts = {
-+ .announce = stdio_announce,
-+ .xterm_title = "Virtual Console #%d",
-+ .raw = 1,
-+ .tramp_stack = 0,
-+ .in_kernel = 1,
-+};
-+
-+static int con_config(char *str);
-+static int con_get_config(char *dev, char *str, int size, char **error_out);
-+static int con_remove(char *str);
-+
-+static struct line_driver driver = {
-+ .name = "UML console",
-+ .devfs_name = "vc/%d",
-+ .major = TTY_MAJOR,
-+ .minor_start = 0,
-+ .type = TTY_DRIVER_TYPE_CONSOLE,
-+ .subtype = SYSTEM_TYPE_CONSOLE,
-+ .read_irq = CONSOLE_IRQ,
-+ .read_irq_name = "console",
-+ .write_irq = CONSOLE_WRITE_IRQ,
-+ .write_irq_name = "console-write",
-+ .symlink_from = "ttys",
-+ .symlink_to = "vc",
-+ .mc = {
-+ .name = "con",
-+ .config = con_config,
-+ .get_config = con_get_config,
-+ .remove = con_remove,
-+ },
-+};
-+
-+static struct lines console_lines = LINES_INIT(MAX_TTYS);
-+
-+/* The array is initialized by line_init, which is an initcall. The
-+ * individual elements are protected by individual semaphores.
-+ */
-+struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver),
-+ [ 1 ... MAX_TTYS - 1 ] =
-+ LINE_INIT(CONFIG_CON_CHAN, &driver) };
-+
-+static int con_config(char *str)
-+{
-+ return(line_config(vts, sizeof(vts)/sizeof(vts[0]), str));
-+}
-+
-+static int con_get_config(char *dev, char *str, int size, char **error_out)
-+{
-+ return(line_get_config(dev, vts, sizeof(vts)/sizeof(vts[0]), str,
-+ size, error_out));
-+}
-+
-+static int con_remove(char *str)
-+{
-+ return(line_remove(vts, sizeof(vts)/sizeof(vts[0]), str));
-+}
-+
-+static int open_console(struct tty_struct *tty)
-+{
-+ return(line_open(vts, tty, &opts));
-+}
-+
-+static int con_open(struct tty_struct *tty, struct file *filp)
-+{
-+ return(open_console(tty));
-+}
-+
-+static void con_close(struct tty_struct *tty, struct file *filp)
-+{
-+ line_close(vts, tty);
-+}
-+
-+static int con_write(struct tty_struct *tty, int from_user,
-+ const unsigned char *buf, int count)
-+{
-+ return(line_write(vts, tty, from_user, buf, count));
-+}
-+
-+static void set_termios(struct tty_struct *tty, struct termios * old)
-+{
-+}
-+
-+static int chars_in_buffer(struct tty_struct *tty)
-+{
-+ return(0);
-+}
-+
-+static int con_init_done = 0;
-+
-+int stdio_init(void)
-+{
-+ char *new_title;
-+
-+ printk(KERN_INFO "Initializing stdio console driver\n");
-+
-+ line_register_devfs(&console_lines, &driver, &console_driver, vts,
-+ sizeof(vts)/sizeof(vts[0]));
-+
-+ lines_init(vts, sizeof(vts)/sizeof(vts[0]));
-+
-+ new_title = add_xterm_umid(opts.xterm_title);
-+ if(new_title != NULL) opts.xterm_title = new_title;
-+
-+ open_console(NULL);
-+ con_init_done = 1;
-+ return(0);
-+}
-+
-+__initcall(stdio_init);
-+
-+static void console_write(struct console *console, const char *string,
-+ unsigned len)
-+{
-+ struct line *line = &vts[console->index];
-+
-+ if(con_init_done)
-+ down(&line->sem);
-+ console_write_chan(&line->chan_list, string, len);
-+ if(con_init_done)
-+ up(&line->sem);
-+}
-+
-+static struct tty_driver console_driver = {
-+ .refcount = &console_refcount,
-+ .open = con_open,
-+ .close = con_close,
-+ .write = con_write,
-+ .chars_in_buffer = chars_in_buffer,
-+ .set_termios = set_termios
-+};
-+
-+static kdev_t console_device(struct console *c)
-+{
-+ return mk_kdev(TTY_MAJOR, c->index);
-+}
-+
-+static int console_setup(struct console *co, char *options)
-+{
-+ return(0);
-+}
-+
-+static struct console stdiocons = {
-+ name: "tty",
-+ write: console_write,
-+ device: console_device,
-+ setup: console_setup,
-+ flags: CON_PRINTBUFFER,
-+ index: -1,
-+};
-+
-+void stdio_console_init(void)
-+{
-+ INIT_LIST_HEAD(&vts[0].chan_list);
-+ list_add(&init_console_chan.list, &vts[0].chan_list);
-+ register_console(&stdiocons);
-+}
-+
-+static int console_chan_setup(char *str)
-+{
-+ return(line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1));
-+}
-+
-+__setup("con", console_chan_setup);
-+__channel_help(console_chan_setup, "con");
-+
-+static void console_exit(void)
-+{
-+ if(!con_init_done) return;
-+ close_lines(vts, sizeof(vts)/sizeof(vts[0]));
-+}
-+
-+__uml_exitcall(console_exit);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/stdio_console.h um/arch/um/drivers/stdio_console.h
---- orig/arch/um/drivers/stdio_console.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/stdio_console.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,21 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __STDIO_CONSOLE_H
-+#define __STDIO_CONSOLE_H
-+
-+extern void save_console_flags(void);
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/tty.c um/arch/um/drivers/tty.c
---- orig/arch/um/drivers/tty.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/tty.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,86 @@
-+/*
-+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdio.h>
-+#include <termios.h>
-+#include <errno.h>
-+#include <unistd.h>
-+#include "chan_user.h"
-+#include "user_util.h"
-+#include "user.h"
-+#include "os.h"
-+
-+struct tty_chan {
-+ char *dev;
-+ int raw;
-+ struct termios tt;
-+};
-+
-+void *tty_chan_init(char *str, int device, struct chan_opts *opts)
-+{
-+ struct tty_chan *data;
-+
-+ if(*str != ':'){
-+ printk("tty_init : channel type 'tty' must specify "
-+ "a device\n");
-+ return(NULL);
-+ }
-+ str++;
-+
-+ data = um_kmalloc(sizeof(*data));
-+ if(data == NULL)
-+ return(NULL);
-+ *data = ((struct tty_chan) { .dev = str,
-+ .raw = opts->raw });
-+
-+ return(data);
-+}
-+
-+int tty_open(int input, int output, int primary, void *d, char **dev_out)
-+{
-+ struct tty_chan *data = d;
-+ int fd;
-+
-+ fd = os_open_file(data->dev, of_set_rw(OPENFLAGS(), input, output), 0);
-+ if(fd < 0) return(fd);
-+ if(data->raw){
-+ tcgetattr(fd, &data->tt);
-+ raw(fd, 0);
-+ }
-+
-+ *dev_out = data->dev;
-+ return(fd);
-+}
-+
-+int tty_console_write(int fd, const char *buf, int n, void *d)
-+{
-+ struct tty_chan *data = d;
-+
-+ return(generic_console_write(fd, buf, n, &data->tt));
-+}
-+
-+struct chan_ops tty_ops = {
-+ .type = "tty",
-+ .init = tty_chan_init,
-+ .open = tty_open,
-+ .close = generic_close,
-+ .read = generic_read,
-+ .write = generic_write,
-+ .console_write = tty_console_write,
-+ .window_size = generic_window_size,
-+ .free = generic_free,
-+ .winch = 0,
-+};
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/ubd_kern.c um/arch/um/drivers/ubd_kern.c
---- orig/arch/um/drivers/ubd_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/ubd_kern.c 2004-01-21 01:28:43.000000000 -0500
-@@ -0,0 +1,1396 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+/* 2001-09-28...2002-04-17
-+ * Partition stuff by James_McMechan@hotmail.com
-+ * old style ubd by setting UBD_SHIFT to 0
-+ */
-+
-+#define MAJOR_NR UBD_MAJOR
-+#define UBD_SHIFT 4
-+
-+#include "linux/config.h"
-+#include "linux/blk.h"
-+#include "linux/blkdev.h"
-+#include "linux/hdreg.h"
-+#include "linux/init.h"
-+#include "linux/devfs_fs_kernel.h"
-+#include "linux/cdrom.h"
-+#include "linux/proc_fs.h"
-+#include "linux/ctype.h"
-+#include "linux/capability.h"
-+#include "linux/mm.h"
-+#include "linux/vmalloc.h"
-+#include "linux/blkpg.h"
-+#include "linux/genhd.h"
-+#include "linux/spinlock.h"
-+#include "asm/segment.h"
-+#include "asm/uaccess.h"
-+#include "asm/irq.h"
-+#include "asm/types.h"
-+#include "user_util.h"
-+#include "mem_user.h"
-+#include "kern_util.h"
-+#include "kern.h"
-+#include "mconsole_kern.h"
-+#include "init.h"
-+#include "irq_user.h"
-+#include "irq_kern.h"
-+#include "ubd_user.h"
-+#include "2_5compat.h"
-+#include "os.h"
-+#include "mem.h"
-+#include "mem_kern.h"
-+
-+static int ubd_open(struct inode * inode, struct file * filp);
-+static int ubd_release(struct inode * inode, struct file * file);
-+static int ubd_ioctl(struct inode * inode, struct file * file,
-+ unsigned int cmd, unsigned long arg);
-+static int ubd_revalidate(kdev_t rdev);
-+static int ubd_revalidate1(kdev_t rdev);
-+
-+#define MAX_DEV (8)
-+#define MAX_MINOR (MAX_DEV << UBD_SHIFT)
-+
-+/* Changed in early boot */
-+static int ubd_do_mmap = 0;
-+#define UBD_MMAP_BLOCK_SIZE PAGE_SIZE
-+
-+/* Not modified by this driver */
-+static int blk_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = BLOCK_SIZE };
-+static int hardsect_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 512 };
-+
-+/* Protected by ubd_lock */
-+static int sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 0 };
-+
-+static struct block_device_operations ubd_blops = {
-+ .open = ubd_open,
-+ .release = ubd_release,
-+ .ioctl = ubd_ioctl,
-+ .revalidate = ubd_revalidate,
-+};
-+
-+/* Protected by ubd_lock, except in prepare_request and ubd_ioctl because
-+ * the block layer should ensure that the device is idle before closing it.
-+ */
-+static struct hd_struct ubd_part[MAX_MINOR] =
-+ { [ 0 ... MAX_MINOR - 1 ] = { 0, 0, 0 } };
-+
-+/* Protected by io_request_lock */
-+static request_queue_t *ubd_queue;
-+
-+/* Protected by ubd_lock */
-+static int fake_major = MAJOR_NR;
-+
-+static spinlock_t ubd_lock = SPIN_LOCK_UNLOCKED;
-+
-+#define INIT_GENDISK(maj, name, parts, shift, bsizes, max, blops) \
-+{ \
-+ .major = maj, \
-+ .major_name = name, \
-+ .minor_shift = shift, \
-+ .max_p = 1 << shift, \
-+ .part = parts, \
-+ .sizes = bsizes, \
-+ .nr_real = max, \
-+ .real_devices = NULL, \
-+ .next = NULL, \
-+ .fops = blops, \
-+ .de_arr = NULL, \
-+ .flags = 0 \
-+}
-+
-+static struct gendisk ubd_gendisk = INIT_GENDISK(MAJOR_NR, "ubd", ubd_part,
-+ UBD_SHIFT, sizes, MAX_DEV,
-+ &ubd_blops);
-+static struct gendisk fake_gendisk = INIT_GENDISK(0, "ubd", ubd_part,
-+ UBD_SHIFT, sizes, MAX_DEV,
-+ &ubd_blops);
-+
-+#ifdef CONFIG_BLK_DEV_UBD_SYNC
-+#define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 1, .c = 0, \
-+ .cl = 1 })
-+#else
-+#define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 0, .c = 0, \
-+ .cl = 1 })
-+#endif
-+
-+/* Not protected - changed only in ubd_setup_common and then only to
-+ * to enable O_SYNC.
-+ */
-+static struct openflags global_openflags = OPEN_FLAGS;
-+
-+struct cow {
-+ char *file;
-+ int fd;
-+ unsigned long *bitmap;
-+ unsigned long bitmap_len;
-+ int bitmap_offset;
-+ int data_offset;
-+};
-+
-+struct ubd {
-+ char *file;
-+ int count;
-+ int fd;
-+ __u64 size;
-+ struct openflags boot_openflags;
-+ struct openflags openflags;
-+ devfs_handle_t devfs;
-+ int no_cow;
-+ struct cow cow;
-+
-+ int map_writes;
-+ int map_reads;
-+ int nomap_writes;
-+ int nomap_reads;
-+ int write_maps;
-+};
-+
-+#define DEFAULT_COW { \
-+ .file = NULL, \
-+ .fd = -1, \
-+ .bitmap = NULL, \
-+ .bitmap_offset = 0, \
-+ .data_offset = 0, \
-+}
-+
-+#define DEFAULT_UBD { \
-+ .file = NULL, \
-+ .count = 0, \
-+ .fd = -1, \
-+ .size = -1, \
-+ .boot_openflags = OPEN_FLAGS, \
-+ .openflags = OPEN_FLAGS, \
-+ .devfs = NULL, \
-+ .no_cow = 0, \
-+ .cow = DEFAULT_COW, \
-+ .map_writes = 0, \
-+ .map_reads = 0, \
-+ .nomap_writes = 0, \
-+ .nomap_reads = 0, \
-+ .write_maps = 0, \
-+}
-+
-+struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD };
-+
-+static int ubd0_init(void)
-+{
-+ struct ubd *dev = &ubd_dev[0];
-+
-+ if(dev->file == NULL)
-+ dev->file = "root_fs";
-+ return(0);
-+}
-+
-+__initcall(ubd0_init);
-+
-+/* Only changed by fake_ide_setup which is a setup */
-+static int fake_ide = 0;
-+static struct proc_dir_entry *proc_ide_root = NULL;
-+static struct proc_dir_entry *proc_ide = NULL;
-+
-+static void make_proc_ide(void)
-+{
-+ proc_ide_root = proc_mkdir("ide", 0);
-+ proc_ide = proc_mkdir("ide0", proc_ide_root);
-+}
-+
-+static int proc_ide_read_media(char *page, char **start, off_t off, int count,
-+ int *eof, void *data)
-+{
-+ int len;
-+
-+ strcpy(page, "disk\n");
-+ len = strlen("disk\n");
-+ len -= off;
-+ if (len < count){
-+ *eof = 1;
-+ if (len <= 0) return 0;
-+ }
-+ else len = count;
-+ *start = page + off;
-+ return len;
-+}
-+
-+static void make_ide_entries(char *dev_name)
-+{
-+ struct proc_dir_entry *dir, *ent;
-+ char name[64];
-+
-+ if(!fake_ide) return;
-+
-+ /* Without locking this could race if a UML was booted with no
-+ * disks and then two mconsole requests which add disks came in
-+ * at the same time.
-+ */
-+ spin_lock(&ubd_lock);
-+ if(proc_ide_root == NULL) make_proc_ide();
-+ spin_unlock(&ubd_lock);
-+
-+ dir = proc_mkdir(dev_name, proc_ide);
-+ if(!dir) return;
-+
-+ ent = create_proc_entry("media", S_IFREG|S_IRUGO, dir);
-+ if(!ent) return;
-+ ent->nlink = 1;
-+ ent->data = NULL;
-+ ent->read_proc = proc_ide_read_media;
-+ ent->write_proc = NULL;
-+ sprintf(name,"ide0/%s", dev_name);
-+ proc_symlink(dev_name, proc_ide_root, name);
-+}
-+
-+static int fake_ide_setup(char *str)
-+{
-+ fake_ide = 1;
-+ return(1);
-+}
-+
-+__setup("fake_ide", fake_ide_setup);
-+
-+__uml_help(fake_ide_setup,
-+"fake_ide\n"
-+" Create ide0 entries that map onto ubd devices.\n\n"
-+);
-+
-+static int parse_unit(char **ptr)
-+{
-+ char *str = *ptr, *end;
-+ int n = -1;
-+
-+ if(isdigit(*str)) {
-+ n = simple_strtoul(str, &end, 0);
-+ if(end == str)
-+ return(-1);
-+ *ptr = end;
-+ }
-+ else if (('a' <= *str) && (*str <= 'h')) {
-+ n = *str - 'a';
-+ str++;
-+ *ptr = str;
-+ }
-+ return(n);
-+}
-+
-+static int ubd_setup_common(char *str, int *index_out)
-+{
-+ struct openflags flags = global_openflags;
-+ struct ubd *dev;
-+ char *backing_file;
-+ int n, err;
-+
-+ if(index_out) *index_out = -1;
-+ n = *str;
-+ if(n == '='){
-+ char *end;
-+ int major;
-+
-+ str++;
-+ if(!strcmp(str, "mmap")){
-+ CHOOSE_MODE(printk("mmap not supported by the ubd "
-+ "driver in tt mode\n"),
-+ ubd_do_mmap = 1);
-+ return(0);
-+ }
-+
-+ if(!strcmp(str, "sync")){
-+ global_openflags.s = 1;
-+ return(0);
-+ }
-+ major = simple_strtoul(str, &end, 0);
-+ if((*end != '\0') || (end == str)){
-+ printk(KERN_ERR
-+ "ubd_setup : didn't parse major number\n");
-+ return(1);
-+ }
-+
-+ err = 1;
-+ spin_lock(&ubd_lock);
-+ if(fake_major != MAJOR_NR){
-+ printk(KERN_ERR "Can't assign a fake major twice\n");
-+ goto out1;
-+ }
-+
-+ fake_gendisk.major = major;
-+ fake_major = major;
-+
-+ printk(KERN_INFO "Setting extra ubd major number to %d\n",
-+ major);
-+ err = 0;
-+ out1:
-+ spin_unlock(&ubd_lock);
-+ return(err);
-+ }
-+
-+ n = parse_unit(&str);
-+ if(n < 0){
-+ printk(KERN_ERR "ubd_setup : couldn't parse unit number "
-+ "'%s'\n", str);
-+ return(1);
-+ }
-+
-+ if(n >= MAX_DEV){
-+ printk(KERN_ERR "ubd_setup : index %d out of range "
-+ "(%d devices)\n", n, MAX_DEV);
-+ return(1);
-+ }
-+
-+ err = 1;
-+ spin_lock(&ubd_lock);
-+
-+ dev = &ubd_dev[n];
-+ if(dev->file != NULL){
-+ printk(KERN_ERR "ubd_setup : device already configured\n");
-+ goto out2;
-+ }
-+
-+ if(index_out) *index_out = n;
-+
-+ if(*str == 'r'){
-+ flags.w = 0;
-+ str++;
-+ }
-+ if(*str == 's'){
-+ flags.s = 1;
-+ str++;
-+ }
-+ if(*str == 'd'){
-+ dev->no_cow = 1;
-+ str++;
-+ }
-+
-+ if(*str++ != '='){
-+ printk(KERN_ERR "ubd_setup : Expected '='\n");
-+ goto out2;
-+ }
-+
-+ err = 0;
-+ backing_file = strchr(str, ',');
-+ if(backing_file){
-+ if(dev->no_cow)
-+ printk(KERN_ERR "Can't specify both 'd' and a "
-+ "cow file\n");
-+ else {
-+ *backing_file = '\0';
-+ backing_file++;
-+ }
-+ }
-+ dev->file = str;
-+ dev->cow.file = backing_file;
-+ dev->boot_openflags = flags;
-+ out2:
-+ spin_unlock(&ubd_lock);
-+ return(err);
-+}
-+
-+static int ubd_setup(char *str)
-+{
-+ ubd_setup_common(str, NULL);
-+ return(1);
-+}
-+
-+__setup("ubd", ubd_setup);
-+__uml_help(ubd_setup,
-+"ubd<n>=<filename>\n"
-+" This is used to associate a device with a file in the underlying\n"
-+" filesystem. Usually, there is a filesystem in the file, but \n"
-+" that's not required. Swap devices containing swap files can be\n"
-+" specified like this. Also, a file which doesn't contain a\n"
-+" filesystem can have its contents read in the virtual \n"
-+" machine by running dd on the device. n must be in the range\n"
-+" 0 to 7. Appending an 'r' to the number will cause that device\n"
-+" to be mounted read-only. For example ubd1r=./ext_fs. Appending\n"
-+" an 's' (has to be _after_ 'r', if there is one) will cause data\n"
-+" to be written to disk on the host immediately.\n\n"
-+);
-+
-+static int fakehd(char *str)
-+{
-+ printk(KERN_INFO
-+ "fakehd : Changing ubd_gendisk.major_name to \"hd\".\n");
-+ ubd_gendisk.major_name = "hd";
-+ return(1);
-+}
-+
-+__setup("fakehd", fakehd);
-+__uml_help(fakehd,
-+"fakehd\n"
-+" Change the ubd device name to \"hd\".\n\n"
-+);
-+
-+static void do_ubd_request(request_queue_t * q);
-+
-+/* Only changed by ubd_init, which is an initcall. */
-+int thread_fd = -1;
-+
-+/* Changed by ubd_handler, which is serialized because interrupts only
-+ * happen on CPU 0.
-+ */
-+int intr_count = 0;
-+
-+static void ubd_finish(int error)
-+{
-+ int nsect;
-+
-+ if(error){
-+ end_request(0);
-+ return;
-+ }
-+ nsect = CURRENT->current_nr_sectors;
-+ CURRENT->sector += nsect;
-+ CURRENT->buffer += nsect << 9;
-+ CURRENT->errors = 0;
-+ CURRENT->nr_sectors -= nsect;
-+ CURRENT->current_nr_sectors = 0;
-+ end_request(1);
-+}
-+
-+static void ubd_handler(void)
-+{
-+ struct io_thread_req req;
-+ int n, err;
-+
-+ DEVICE_INTR = NULL;
-+ intr_count++;
-+ n = read_ubd_fs(thread_fd, &req, sizeof(req));
-+ if(n != sizeof(req)){
-+ printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, "
-+ "err = %d\n", os_getpid(), -n);
-+ spin_lock(&io_request_lock);
-+ end_request(0);
-+ spin_unlock(&io_request_lock);
-+ return;
-+ }
-+
-+ if((req.op != UBD_MMAP) &&
-+ ((req.offset != ((__u64) (CURRENT->sector)) << 9) ||
-+ (req.length != (CURRENT->current_nr_sectors) << 9)))
-+ panic("I/O op mismatch");
-+
-+ if(req.map_fd != -1){
-+ err = physmem_subst_mapping(req.buffer, req.map_fd,
-+ req.map_offset, 1);
-+ if(err)
-+ printk("ubd_handler - physmem_subst_mapping failed, "
-+ "err = %d\n", -err);
-+ }
-+
-+ spin_lock(&io_request_lock);
-+ ubd_finish(req.error);
-+ reactivate_fd(thread_fd, UBD_IRQ);
-+ do_ubd_request(ubd_queue);
-+ spin_unlock(&io_request_lock);
-+}
-+
-+static void ubd_intr(int irq, void *dev, struct pt_regs *unused)
-+{
-+ ubd_handler();
-+}
-+
-+/* Only changed by ubd_init, which is an initcall. */
-+static int io_pid = -1;
-+
-+void kill_io_thread(void)
-+{
-+ if(io_pid != -1)
-+ os_kill_process(io_pid, 1);
-+}
-+
-+__uml_exitcall(kill_io_thread);
-+
-+/* Initialized in an initcall, and unchanged thereafter */
-+devfs_handle_t ubd_dir_handle;
-+
-+static int ubd_add(int n)
-+{
-+ struct ubd *dev = &ubd_dev[n];
-+ char name[sizeof("nnnnnn\0")], dev_name[sizeof("ubd0x")];
-+ int err = -EISDIR;
-+
-+ if(dev->file == NULL)
-+ goto out;
-+
-+ err = ubd_revalidate1(MKDEV(MAJOR_NR, n << UBD_SHIFT));
-+ if(err)
-+ goto out;
-+
-+ if(dev->cow.file == NULL)
-+ blk_sizes[n] = UBD_MMAP_BLOCK_SIZE;
-+
-+ sprintf(name, "%d", n);
-+ dev->devfs = devfs_register(ubd_dir_handle, name, DEVFS_FL_REMOVABLE,
-+ MAJOR_NR, n << UBD_SHIFT, S_IFBLK |
-+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
-+ &ubd_blops, NULL);
-+
-+#if 0 /* 2.5 ... */
-+ sprintf(disk->disk_name, "ubd%c", 'a' + unit);
-+#endif
-+
-+ sprintf(dev_name, "%s%c", ubd_gendisk.major_name,
-+ n + 'a');
-+
-+ make_ide_entries(dev_name);
-+ return(0);
-+
-+ out:
-+ return(err);
-+}
-+
-+static int ubd_config(char *str)
-+{
-+ int n, err;
-+
-+ str = uml_strdup(str);
-+ if(str == NULL){
-+ printk(KERN_ERR "ubd_config failed to strdup string\n");
-+ return(1);
-+ }
-+ err = ubd_setup_common(str, &n);
-+ if(err){
-+ kfree(str);
-+ return(-1);
-+ }
-+ if(n == -1) return(0);
-+
-+ spin_lock(&ubd_lock);
-+ err = ubd_add(n);
-+ if(err)
-+ ubd_dev[n].file = NULL;
-+ spin_unlock(&ubd_lock);
-+
-+ return(err);
-+}
-+
-+static int ubd_get_config(char *name, char *str, int size, char **error_out)
-+{
-+ struct ubd *dev;
-+ char *end;
-+ int n, len = 0;
-+
-+ n = simple_strtoul(name, &end, 0);
-+ if((*end != '\0') || (end == name)){
-+ *error_out = "ubd_get_config : didn't parse device number";
-+ return(-1);
-+ }
-+
-+ if((n >= MAX_DEV) || (n < 0)){
-+ *error_out = "ubd_get_config : device number out of range";
-+ return(-1);
-+ }
-+
-+ dev = &ubd_dev[n];
-+ spin_lock(&ubd_lock);
-+
-+ if(dev->file == NULL){
-+ CONFIG_CHUNK(str, size, len, "", 1);
-+ goto out;
-+ }
-+
-+ CONFIG_CHUNK(str, size, len, dev->file, 0);
-+
-+ if(dev->cow.file != NULL){
-+ CONFIG_CHUNK(str, size, len, ",", 0);
-+ CONFIG_CHUNK(str, size, len, dev->cow.file, 1);
-+ }
-+ else CONFIG_CHUNK(str, size, len, "", 1);
-+
-+ out:
-+ spin_unlock(&ubd_lock);
-+ return(len);
-+}
-+
-+static int ubd_remove(char *str)
-+{
-+ struct ubd *dev;
-+ int n, err = -ENODEV;
-+
-+ if(isdigit(*str)){
-+ char *end;
-+ n = simple_strtoul(str, &end, 0);
-+ if ((*end != '\0') || (end == str))
-+ return(err);
-+ }
-+ else if (('a' <= *str) && (*str <= 'h'))
-+ n = *str - 'a';
-+ else
-+ return(err); /* it should be a number 0-7/a-h */
-+
-+ if((n < 0) || (n >= MAX_DEV))
-+ return(err);
-+
-+ dev = &ubd_dev[n];
-+
-+ spin_lock(&ubd_lock);
-+ err = 0;
-+ if(dev->file == NULL)
-+ goto out;
-+ err = -1;
-+ if(dev->count > 0)
-+ goto out;
-+ if(dev->devfs != NULL)
-+ devfs_unregister(dev->devfs);
-+
-+ *dev = ((struct ubd) DEFAULT_UBD);
-+ err = 0;
-+ out:
-+ spin_unlock(&ubd_lock);
-+ return(err);
-+}
-+
-+static struct mc_device ubd_mc = {
-+ .name = "ubd",
-+ .config = ubd_config,
-+ .get_config = ubd_get_config,
-+ .remove = ubd_remove,
-+};
-+
-+static int ubd_mc_init(void)
-+{
-+ mconsole_register_dev(&ubd_mc);
-+ return(0);
-+}
-+
-+__initcall(ubd_mc_init);
-+
-+static request_queue_t *ubd_get_queue(kdev_t device)
-+{
-+ return(ubd_queue);
-+}
-+
-+int ubd_init(void)
-+{
-+ unsigned long stack;
-+ int i, err;
-+
-+ ubd_dir_handle = devfs_mk_dir (NULL, "ubd", NULL);
-+ if (devfs_register_blkdev(MAJOR_NR, "ubd", &ubd_blops)) {
-+ printk(KERN_ERR "ubd: unable to get major %d\n", MAJOR_NR);
-+ return -1;
-+ }
-+ read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */
-+ blksize_size[MAJOR_NR] = blk_sizes;
-+ blk_size[MAJOR_NR] = sizes;
-+ INIT_HARDSECT(hardsect_size, MAJOR_NR, hardsect_sizes);
-+
-+ ubd_queue = BLK_DEFAULT_QUEUE(MAJOR_NR);
-+ blk_init_queue(ubd_queue, DEVICE_REQUEST);
-+ INIT_ELV(ubd_queue, &ubd_queue->elevator);
-+
-+ add_gendisk(&ubd_gendisk);
-+ if (fake_major != MAJOR_NR){
-+ /* major number 0 is used to auto select */
-+ err = devfs_register_blkdev(fake_major, "fake", &ubd_blops);
-+ if(fake_major == 0){
-+ /* auto device number case */
-+ fake_major = err;
-+ if(err == 0)
-+ return(-ENODEV);
-+ }
-+ else if (err){
-+ /* not auto so normal error */
-+ printk(KERN_ERR "ubd: error %d getting major %d\n",
-+ -err, fake_major);
-+ return(-ENODEV);
-+ }
-+
-+ blk_dev[fake_major].queue = ubd_get_queue;
-+ read_ahead[fake_major] = 8; /* 8 sector (4kB) read-ahead */
-+ blksize_size[fake_major] = blk_sizes;
-+ blk_size[fake_major] = sizes;
-+ INIT_HARDSECT(hardsect_size, fake_major, hardsect_sizes);
-+ add_gendisk(&fake_gendisk);
-+ }
-+
-+ for(i=0;i<MAX_DEV;i++)
-+ ubd_add(i);
-+
-+ if(global_openflags.s){
-+ printk(KERN_INFO "ubd : Synchronous mode\n");
-+ return(0);
-+ }
-+ stack = alloc_stack(0, 0);
-+ io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *),
-+ &thread_fd);
-+ if(io_pid < 0){
-+ io_pid = -1;
-+ printk(KERN_ERR
-+ "ubd : Failed to start I/O thread (errno = %d) - "
-+ "falling back to synchronous I/O\n", -io_pid);
-+ return(0);
-+ }
-+ err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr,
-+ SA_INTERRUPT, "ubd", ubd_dev);
-+ if(err != 0)
-+ printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err);
-+ return(err);
-+}
-+
-+__initcall(ubd_init);
-+
-+static void ubd_close(struct ubd *dev)
-+{
-+ if(ubd_do_mmap)
-+ physmem_forget_descriptor(dev->fd);
-+ os_close_file(dev->fd);
-+ if(dev->cow.file != NULL)
-+ return;
-+
-+ if(ubd_do_mmap)
-+ physmem_forget_descriptor(dev->cow.fd);
-+ os_close_file(dev->cow.fd);
-+ vfree(dev->cow.bitmap);
-+ dev->cow.bitmap = NULL;
-+}
-+
-+static int ubd_open_dev(struct ubd *dev)
-+{
-+ struct openflags flags;
-+ char **back_ptr;
-+ int err, create_cow, *create_ptr;
-+
-+ dev->openflags = dev->boot_openflags;
-+ create_cow = 0;
-+ create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL;
-+ back_ptr = dev->no_cow ? NULL : &dev->cow.file;
-+ dev->fd = open_ubd_file(dev->file, &dev->openflags, back_ptr,
-+ &dev->cow.bitmap_offset, &dev->cow.bitmap_len,
-+ &dev->cow.data_offset, create_ptr);
-+
-+ if((dev->fd == -ENOENT) && create_cow){
-+ dev->fd = create_cow_file(dev->file, dev->cow.file,
-+ dev->openflags, 1 << 9, PAGE_SIZE,
-+ &dev->cow.bitmap_offset,
-+ &dev->cow.bitmap_len,
-+ &dev->cow.data_offset);
-+ if(dev->fd >= 0){
-+ printk(KERN_INFO "Creating \"%s\" as COW file for "
-+ "\"%s\"\n", dev->file, dev->cow.file);
-+ }
-+ }
-+
-+ if(dev->fd < 0) return(dev->fd);
-+
-+ if(dev->cow.file != NULL){
-+ err = -ENOMEM;
-+ dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len);
-+ if(dev->cow.bitmap == NULL){
-+ printk(KERN_ERR "Failed to vmalloc COW bitmap\n");
-+ goto error;
-+ }
-+ flush_tlb_kernel_vm();
-+
-+ err = read_cow_bitmap(dev->fd, dev->cow.bitmap,
-+ dev->cow.bitmap_offset,
-+ dev->cow.bitmap_len);
-+ if(err < 0)
-+ goto error;
-+
-+ flags = dev->openflags;
-+ flags.w = 0;
-+ err = open_ubd_file(dev->cow.file, &flags, NULL, NULL, NULL,
-+ NULL, NULL);
-+ if(err < 0) goto error;
-+ dev->cow.fd = err;
-+ }
-+ return(0);
-+ error:
-+ os_close_file(dev->fd);
-+ return(err);
-+}
-+
-+static int ubd_file_size(struct ubd *dev, __u64 *size_out)
-+{
-+ char *file;
-+
-+ file = dev->cow.file ? dev->cow.file : dev->file;
-+ return(os_file_size(file, size_out));
-+}
-+
-+static int ubd_open(struct inode *inode, struct file *filp)
-+{
-+ struct ubd *dev;
-+ int n, offset, err = 0;
-+
-+ n = DEVICE_NR(inode->i_rdev);
-+ dev = &ubd_dev[n];
-+ if(n >= MAX_DEV)
-+ return -ENODEV;
-+
-+ spin_lock(&ubd_lock);
-+ offset = n << UBD_SHIFT;
-+
-+ if(dev->count == 0){
-+ err = ubd_open_dev(dev);
-+ if(err){
-+ printk(KERN_ERR "ubd%d: Can't open \"%s\": "
-+ "errno = %d\n", n, dev->file, -err);
-+ goto out;
-+ }
-+ err = ubd_file_size(dev, &dev->size);
-+ if(err < 0)
-+ goto out;
-+ sizes[offset] = dev->size / BLOCK_SIZE;
-+ ubd_part[offset].nr_sects = dev->size / hardsect_sizes[offset];
-+ }
-+ dev->count++;
-+ if((filp->f_mode & FMODE_WRITE) && !dev->openflags.w){
-+ if(--dev->count == 0) ubd_close(dev);
-+ err = -EROFS;
-+ }
-+ out:
-+ spin_unlock(&ubd_lock);
-+ return(err);
-+}
-+
-+static int ubd_release(struct inode * inode, struct file * file)
-+{
-+ int n, offset;
-+
-+ n = DEVICE_NR(inode->i_rdev);
-+ offset = n << UBD_SHIFT;
-+ if(n >= MAX_DEV)
-+ return -ENODEV;
-+
-+ spin_lock(&ubd_lock);
-+ if(--ubd_dev[n].count == 0)
-+ ubd_close(&ubd_dev[n]);
-+ spin_unlock(&ubd_lock);
-+
-+ return(0);
-+}
-+
-+static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask,
-+ __u64 *cow_offset, unsigned long *bitmap,
-+ __u64 bitmap_offset, unsigned long *bitmap_words,
-+ __u64 bitmap_len)
-+{
-+ __u64 sector = io_offset >> 9;
-+ int i, update_bitmap = 0;
-+
-+ for(i = 0; i < length >> 9; i++){
-+ if(cow_mask != NULL)
-+ ubd_set_bit(i, (unsigned char *) cow_mask);
-+ if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
-+ continue;
-+
-+ update_bitmap = 1;
-+ ubd_set_bit(sector + i, (unsigned char *) bitmap);
-+ }
-+
-+ if(!update_bitmap)
-+ return;
-+
-+ *cow_offset = sector / (sizeof(unsigned long) * 8);
-+
-+ /* This takes care of the case where we're exactly at the end of the
-+ * device, and *cow_offset + 1 is off the end. So, just back it up
-+ * by one word. Thanks to Lynn Kerby for the fix and James McMechan
-+ * for the original diagnosis.
-+ */
-+ if(*cow_offset == ((bitmap_len + sizeof(unsigned long) - 1) /
-+ sizeof(unsigned long) - 1))
-+ (*cow_offset)--;
-+
-+ bitmap_words[0] = bitmap[*cow_offset];
-+ bitmap_words[1] = bitmap[*cow_offset + 1];
-+
-+ *cow_offset *= sizeof(unsigned long);
-+ *cow_offset += bitmap_offset;
-+}
-+
-+static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
-+ __u64 bitmap_offset, __u64 bitmap_len)
-+{
-+ __u64 sector = req->offset >> 9;
-+ int i;
-+
-+ if(req->length > (sizeof(req->sector_mask) * 8) << 9)
-+ panic("Operation too long");
-+
-+ if(req->op == UBD_READ) {
-+ for(i = 0; i < req->length >> 9; i++){
-+ if(ubd_test_bit(sector + i, (unsigned char *) bitmap)){
-+ ubd_set_bit(i, (unsigned char *)
-+ &req->sector_mask);
-+ }
-+ }
-+ }
-+ else cowify_bitmap(req->offset, req->length, &req->sector_mask,
-+ &req->cow_offset, bitmap, bitmap_offset,
-+ req->bitmap_words, bitmap_len);
-+}
-+
-+static int mmap_fd(struct request *req, struct ubd *dev, __u64 offset)
-+{
-+ __u64 sector;
-+ unsigned char *bitmap;
-+ int bit, i;
-+
-+ /* mmap must have been requested on the command line */
-+ if(!ubd_do_mmap)
-+ return(-1);
-+
-+ /* The buffer must be page aligned */
-+ if(((unsigned long) req->buffer % UBD_MMAP_BLOCK_SIZE) != 0)
-+ return(-1);
-+
-+ /* The request must be a page long */
-+ if((req->current_nr_sectors << 9) != PAGE_SIZE)
-+ return(-1);
-+
-+ if(dev->cow.file == NULL)
-+ return(dev->fd);
-+
-+ sector = offset >> 9;
-+ bitmap = (unsigned char *) dev->cow.bitmap;
-+ bit = ubd_test_bit(sector, bitmap);
-+
-+ for(i = 1; i < req->current_nr_sectors; i++){
-+ if(ubd_test_bit(sector + i, bitmap) != bit)
-+ return(-1);
-+ }
-+
-+ if(bit || (req->cmd == WRITE))
-+ offset += dev->cow.data_offset;
-+
-+ /* The data on disk must be page aligned */
-+ if((offset % UBD_MMAP_BLOCK_SIZE) != 0)
-+ return(-1);
-+
-+ return(bit ? dev->fd : dev->cow.fd);
-+}
-+
-+static int prepare_mmap_request(struct ubd *dev, int fd, __u64 offset,
-+ struct request *req,
-+ struct io_thread_req *io_req)
-+{
-+ int err;
-+
-+ if(req->cmd == WRITE){
-+ /* Writes are almost no-ops since the new data is already in the
-+ * host page cache
-+ */
-+ dev->map_writes++;
-+ if(dev->cow.file != NULL)
-+ cowify_bitmap(io_req->offset, io_req->length,
-+ &io_req->sector_mask, &io_req->cow_offset,
-+ dev->cow.bitmap, dev->cow.bitmap_offset,
-+ io_req->bitmap_words,
-+ dev->cow.bitmap_len);
-+ }
-+ else {
-+ int w;
-+
-+ if((dev->cow.file != NULL) && (fd == dev->cow.fd))
-+ w = 0;
-+ else w = dev->openflags.w;
-+
-+ if((dev->cow.file != NULL) && (fd == dev->fd))
-+ offset += dev->cow.data_offset;
-+
-+ err = physmem_subst_mapping(req->buffer, fd, offset, w);
-+ if(err){
-+ printk("physmem_subst_mapping failed, err = %d\n",
-+ -err);
-+ return(1);
-+ }
-+ dev->map_reads++;
-+ }
-+ io_req->op = UBD_MMAP;
-+ io_req->buffer = req->buffer;
-+ return(0);
-+}
-+
-+static int prepare_request(struct request *req, struct io_thread_req *io_req)
-+{
-+ struct ubd *dev;
-+ __u64 offset;
-+ int minor, n, len, fd;
-+
-+ if(req->rq_status == RQ_INACTIVE) return(1);
-+
-+ minor = MINOR(req->rq_dev);
-+ n = minor >> UBD_SHIFT;
-+ dev = &ubd_dev[n];
-+
-+ if(IS_WRITE(req) && !dev->openflags.w){
-+ printk("Write attempted on readonly ubd device %d\n", n);
-+ end_request(0);
-+ return(1);
-+ }
-+
-+ req->sector += ubd_part[minor].start_sect;
-+ offset = ((__u64) req->sector) << 9;
-+ len = req->current_nr_sectors << 9;
-+
-+ io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd;
-+ io_req->fds[1] = dev->fd;
-+ io_req->map_fd = -1;
-+ io_req->cow_offset = -1;
-+ io_req->offset = offset;
-+ io_req->length = len;
-+ io_req->error = 0;
-+ io_req->sector_mask = 0;
-+
-+ fd = mmap_fd(req, dev, io_req->offset);
-+ if(fd > 0){
-+ /* If mmapping is otherwise OK, but the first access to the
-+ * page is a write, then it's not mapped in yet. So we have
-+ * to write the data to disk first, then we can map the disk
-+ * page in and continue normally from there.
-+ */
-+ if((req->cmd == WRITE) && !is_remapped(req->buffer)){
-+ io_req->map_fd = dev->fd;
-+ io_req->map_offset = io_req->offset +
-+ dev->cow.data_offset;
-+ dev->write_maps++;
-+ }
-+ else return(prepare_mmap_request(dev, fd, io_req->offset, req,
-+ io_req));
-+ }
-+
-+ if(req->cmd == READ)
-+ dev->nomap_reads++;
-+ else dev->nomap_writes++;
-+
-+ io_req->op = (req->cmd == READ) ? UBD_READ : UBD_WRITE;
-+ io_req->offsets[0] = 0;
-+ io_req->offsets[1] = dev->cow.data_offset;
-+ io_req->buffer = req->buffer;
-+ io_req->sectorsize = 1 << 9;
-+
-+ if(dev->cow.file != NULL)
-+ cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset,
-+ dev->cow.bitmap_len);
-+ return(0);
-+}
-+
-+static void do_ubd_request(request_queue_t *q)
-+{
-+ struct io_thread_req io_req;
-+ struct request *req;
-+ int err, n;
-+
-+ if(thread_fd == -1){
-+ while(!list_empty(&q->queue_head)){
-+ req = blkdev_entry_next_request(&q->queue_head);
-+ err = prepare_request(req, &io_req);
-+ if(!err){
-+ do_io(&io_req);
-+ ubd_finish(io_req.error);
-+ }
-+ }
-+ }
-+ else {
-+ if(DEVICE_INTR || list_empty(&q->queue_head)) return;
-+ req = blkdev_entry_next_request(&q->queue_head);
-+ err = prepare_request(req, &io_req);
-+ if(!err){
-+ SET_INTR(ubd_handler);
-+ n = write_ubd_fs(thread_fd, (char *) &io_req,
-+ sizeof(io_req));
-+ if(n != sizeof(io_req))
-+ printk("write to io thread failed, "
-+ "errno = %d\n", -n);
-+ }
-+ }
-+}
-+
-+static int ubd_ioctl(struct inode * inode, struct file * file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ struct hd_geometry *loc = (struct hd_geometry *) arg;
-+ struct ubd *dev;
-+ int n, minor, err;
-+ struct hd_driveid ubd_id = {
-+ .cyls = 0,
-+ .heads = 128,
-+ .sectors = 32,
-+ };
-+
-+ if(!inode) return(-EINVAL);
-+ minor = MINOR(inode->i_rdev);
-+ n = minor >> UBD_SHIFT;
-+ if(n >= MAX_DEV)
-+ return(-EINVAL);
-+ dev = &ubd_dev[n];
-+ switch (cmd) {
-+ struct hd_geometry g;
-+ struct cdrom_volctrl volume;
-+ case HDIO_GETGEO:
-+ if(!loc) return(-EINVAL);
-+ g.heads = 128;
-+ g.sectors = 32;
-+ g.cylinders = dev->size / (128 * 32 * hardsect_sizes[minor]);
-+ g.start = ubd_part[minor].start_sect;
-+ return(copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0);
-+ case BLKGETSIZE: /* Return device size */
-+ if(!arg) return(-EINVAL);
-+ err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
-+ if(err)
-+ return(err);
-+ put_user(ubd_part[minor].nr_sects, (long *) arg);
-+ return(0);
-+ case BLKRRPART: /* Re-read partition tables */
-+ return(ubd_revalidate(inode->i_rdev));
-+
-+ case HDIO_SET_UNMASKINTR:
-+ if(!capable(CAP_SYS_ADMIN)) return(-EACCES);
-+ if((arg > 1) || (minor & 0x3F)) return(-EINVAL);
-+ return(0);
-+
-+ case HDIO_GET_UNMASKINTR:
-+ if(!arg) return(-EINVAL);
-+ err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
-+ if(err)
-+ return(err);
-+ return(0);
-+
-+ case HDIO_GET_MULTCOUNT:
-+ if(!arg) return(-EINVAL);
-+ err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
-+ if(err)
-+ return(err);
-+ return(0);
-+
-+ case HDIO_SET_MULTCOUNT:
-+ if(!capable(CAP_SYS_ADMIN)) return(-EACCES);
-+ if(MINOR(inode->i_rdev) & 0x3F) return(-EINVAL);
-+ return(0);
-+
-+ case HDIO_GET_IDENTITY:
-+ ubd_id.cyls = dev->size / (128 * 32 * hardsect_sizes[minor]);
-+ if(copy_to_user((char *) arg, (char *) &ubd_id,
-+ sizeof(ubd_id)))
-+ return(-EFAULT);
-+ return(0);
-+
-+ case CDROMVOLREAD:
-+ if(copy_from_user(&volume, (char *) arg, sizeof(volume)))
-+ return(-EFAULT);
-+ volume.channel0 = 255;
-+ volume.channel1 = 255;
-+ volume.channel2 = 255;
-+ volume.channel3 = 255;
-+ if(copy_to_user((char *) arg, &volume, sizeof(volume)))
-+ return(-EFAULT);
-+ return(0);
-+
-+ default:
-+ return blk_ioctl(inode->i_rdev, cmd, arg);
-+ }
-+}
-+
-+static int ubd_revalidate1(kdev_t rdev)
-+{
-+ int i, n, offset, err = 0, pcount = 1 << UBD_SHIFT;
-+ struct ubd *dev;
-+ struct hd_struct *part;
-+
-+ n = DEVICE_NR(rdev);
-+ offset = n << UBD_SHIFT;
-+ dev = &ubd_dev[n];
-+
-+ part = &ubd_part[offset];
-+
-+ /* clear all old partition counts */
-+ for(i = 1; i < pcount; i++) {
-+ part[i].start_sect = 0;
-+ part[i].nr_sects = 0;
-+ }
-+
-+ /* If it already has been opened we can check the partitions
-+ * directly
-+ */
-+ if(dev->count){
-+ part->start_sect = 0;
-+ register_disk(&ubd_gendisk, MKDEV(MAJOR_NR, offset), pcount,
-+ &ubd_blops, part->nr_sects);
-+ }
-+ else if(dev->file){
-+ err = ubd_open_dev(dev);
-+ if(err){
-+ printk(KERN_ERR "unable to open %s for validation\n",
-+ dev->file);
-+ goto out;
-+ }
-+
-+ /* have to recompute sizes since we opened it */
-+ err = ubd_file_size(dev, &dev->size);
-+ if(err < 0) {
-+ ubd_close(dev);
-+ goto out;
-+ }
-+ part->start_sect = 0;
-+ part->nr_sects = dev->size / hardsect_sizes[offset];
-+ register_disk(&ubd_gendisk, MKDEV(MAJOR_NR, offset), pcount,
-+ &ubd_blops, part->nr_sects);
-+
-+ /* we are done so close it */
-+ ubd_close(dev);
-+ }
-+ else err = -ENODEV;
-+ out:
-+ return(err);
-+}
-+
-+static int ubd_revalidate(kdev_t rdev)
-+{
-+ int err;
-+
-+ spin_lock(&ubd_lock);
-+ err = ubd_revalidate1(rdev);
-+ spin_unlock(&ubd_lock);
-+ return(err);
-+}
-+
-+static int ubd_check_remapped(int fd, unsigned long address, int is_write,
-+ __u64 offset)
-+{
-+ __u64 bitmap_offset;
-+ unsigned long new_bitmap[2];
-+ int i, err, n;
-+
-+ /* If it's not a write access, we can't do anything about it */
-+ if(!is_write)
-+ return(0);
-+
-+ /* We have a write */
-+ for(i = 0; i < sizeof(ubd_dev) / sizeof(ubd_dev[0]); i++){
-+ struct ubd *dev = &ubd_dev[i];
-+
-+ if((dev->fd != fd) && (dev->cow.fd != fd))
-+ continue;
-+
-+ /* It's a write to a ubd device */
-+
-+ if(!dev->openflags.w){
-+ /* It's a write access on a read-only device - probably
-+ * shouldn't happen. If the kernel is trying to change
-+ * something with no intention of writing it back out,
-+ * then this message will clue us in that this needs
-+ * fixing
-+ */
-+ printk("Write access to mapped page from readonly ubd "
-+ "device %d\n", i);
-+ return(0);
-+ }
-+
-+ /* It's a write to a writeable ubd device - it must be COWed
-+ * because, otherwise, the page would have been mapped in
-+ * writeable
-+ */
-+
-+ if(!dev->cow.file)
-+ panic("Write fault on writeable non-COW ubd device %d",
-+ i);
-+
-+ /* It should also be an access to the backing file since the
-+ * COW pages should be mapped in read-write
-+ */
-+
-+ if(fd == dev->fd)
-+ panic("Write fault on a backing page of ubd "
-+ "device %d\n", i);
-+
-+ /* So, we do the write, copying the backing data to the COW
-+ * file...
-+ */
-+
-+ err = os_seek_file(dev->fd, offset + dev->cow.data_offset);
-+ if(err < 0)
-+ panic("Couldn't seek to %lld in COW file of ubd "
-+ "device %d, err = %d",
-+ offset + dev->cow.data_offset, i, -err);
-+
-+ n = os_write_file(dev->fd, (void *) address, PAGE_SIZE);
-+ if(n != PAGE_SIZE)
-+ panic("Couldn't copy data to COW file of ubd "
-+ "device %d, err = %d", i, -n);
-+
-+ /* ... updating the COW bitmap... */
-+
-+ cowify_bitmap(offset, PAGE_SIZE, NULL, &bitmap_offset,
-+ dev->cow.bitmap, dev->cow.bitmap_offset,
-+ new_bitmap, dev->cow.bitmap_len);
-+
-+ err = os_seek_file(dev->fd, bitmap_offset);
-+ if(err < 0)
-+ panic("Couldn't seek to %lld in COW file of ubd "
-+ "device %d, err = %d", bitmap_offset, i, -err);
-+
-+ n = os_write_file(dev->fd, new_bitmap, sizeof(new_bitmap));
-+ if(n != sizeof(new_bitmap))
-+ panic("Couldn't update bitmap of ubd device %d, "
-+ "err = %d", i, -n);
-+
-+ /* Maybe we can map the COW page in, and maybe we can't. If
-+ * it is a pre-V3 COW file, we can't, since the alignment will
-+ * be wrong. If it is a V3 or later COW file which has been
-+ * moved to a system with a larger page size, then maybe we
-+ * can't, depending on the exact location of the page.
-+ */
-+
-+ offset += dev->cow.data_offset;
-+
-+ /* Remove the remapping, putting the original anonymous page
-+ * back. If the COW file can be mapped in, that is done.
-+ * Otherwise, the COW page is read in.
-+ */
-+
-+ if(!physmem_remove_mapping((void *) address))
-+ panic("Address 0x%lx not remapped by ubd device %d",
-+ address, i);
-+ if((offset % UBD_MMAP_BLOCK_SIZE) == 0)
-+ physmem_subst_mapping((void *) address, dev->fd,
-+ offset, 1);
-+ else {
-+ err = os_seek_file(dev->fd, offset);
-+ if(err < 0)
-+ panic("Couldn't seek to %lld in COW file of "
-+ "ubd device %d, err = %d", offset, i,
-+ -err);
-+
-+ n = os_read_file(dev->fd, (void *) address, PAGE_SIZE);
-+ if(n != PAGE_SIZE)
-+ panic("Failed to read page from offset %llx of "
-+ "COW file of ubd device %d, err = %d",
-+ offset, i, -n);
-+ }
-+
-+ return(1);
-+ }
-+
-+ /* It's not a write on a ubd device */
-+ return(0);
-+}
-+
-+static struct remapper ubd_remapper = {
-+ .list = LIST_HEAD_INIT(ubd_remapper.list),
-+ .proc = ubd_check_remapped,
-+};
-+
-+static int ubd_remapper_setup(void)
-+{
-+ if(ubd_do_mmap)
-+ register_remapper(&ubd_remapper);
-+
-+ return(0);
-+}
-+
-+__initcall(ubd_remapper_setup);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/ubd_user.c um/arch/um/drivers/ubd_user.c
---- orig/arch/um/drivers/ubd_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/ubd_user.c 2004-01-10 06:24:52.000000000 -0500
-@@ -0,0 +1,377 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Copyright (C) 2001 Ridgerun,Inc (glonnon@ridgerun.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stddef.h>
-+#include <unistd.h>
-+#include <errno.h>
-+#include <sched.h>
-+#include <signal.h>
-+#include <string.h>
-+#include <netinet/in.h>
-+#include <sys/time.h>
-+#include <sys/socket.h>
-+#include <sys/mman.h>
-+#include <sys/param.h>
-+#include "asm/types.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "user.h"
-+#include "ubd_user.h"
-+#include "os.h"
-+#include "cow.h"
-+
-+#include <endian.h>
-+#include <byteswap.h>
-+
-+static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
-+{
-+ struct uml_stat buf1, buf2;
-+ int err;
-+
-+ if(from_cmdline == NULL) return(1);
-+ if(!strcmp(from_cmdline, from_cow)) return(1);
-+
-+ err = os_stat_file(from_cmdline, &buf1);
-+ if(err < 0){
-+ printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err);
-+ return(1);
-+ }
-+ err = os_stat_file(from_cow, &buf2);
-+ if(err < 0){
-+ printk("Couldn't stat '%s', err = %d\n", from_cow, -err);
-+ return(1);
-+ }
-+ if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino))
-+ return(1);
-+
-+ printk("Backing file mismatch - \"%s\" requested,\n"
-+ "\"%s\" specified in COW header of \"%s\"\n",
-+ from_cmdline, from_cow, cow);
-+ return(0);
-+}
-+
-+static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
-+{
-+ unsigned long modtime;
-+ long long actual;
-+ int err;
-+
-+ err = os_file_modtime(file, &modtime);
-+ if(err < 0){
-+ printk("Failed to get modification time of backing file "
-+ "\"%s\", err = %d\n", file, -err);
-+ return(err);
-+ }
-+
-+ err = os_file_size(file, &actual);
-+ if(err < 0){
-+ printk("Failed to get size of backing file \"%s\", "
-+ "err = %d\n", file, -err);
-+ return(err);
-+ }
-+
-+ if(actual != size){
-+ printk("Size mismatch (%ld vs %ld) of COW header vs backing "
-+ "file\n", size, actual);
-+ return(-EINVAL);
-+ }
-+ if(modtime != mtime){
-+ printk("mtime mismatch (%ld vs %ld) of COW header vs backing "
-+ "file\n", mtime, modtime);
-+ return(-EINVAL);
-+ }
-+ return(0);
-+}
-+
-+int read_cow_bitmap(int fd, void *buf, int offset, int len)
-+{
-+ int err;
-+
-+ err = os_seek_file(fd, offset);
-+ if(err < 0)
-+ return(err);
-+
-+ err = os_read_file(fd, buf, len);
-+ if(err < 0)
-+ return(err);
-+
-+ return(0);
-+}
-+
-+int open_ubd_file(char *file, struct openflags *openflags,
-+ char **backing_file_out, int *bitmap_offset_out,
-+ unsigned long *bitmap_len_out, int *data_offset_out,
-+ int *create_cow_out)
-+{
-+ time_t mtime;
-+ __u64 size;
-+ __u32 version, align;
-+ char *backing_file;
-+ int fd, err, sectorsize, same, mode = 0644;
-+
-+ fd = os_open_file(file, *openflags, mode);
-+ if(fd < 0){
-+ if((fd == -ENOENT) && (create_cow_out != NULL))
-+ *create_cow_out = 1;
-+ if(!openflags->w ||
-+ ((errno != EROFS) && (errno != EACCES))) return(-errno);
-+ openflags->w = 0;
-+ fd = os_open_file(file, *openflags, mode);
-+ if(fd < 0)
-+ return(fd);
-+ }
-+
-+ err = os_lock_file(fd, openflags->w);
-+ if(err < 0){
-+ printk("Failed to lock '%s', err = %d\n", file, -err);
-+ goto out_close;
-+ }
-+
-+ if(backing_file_out == NULL) return(fd);
-+
-+ err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
-+ &size, §orsize, &align, bitmap_offset_out);
-+ if(err && (*backing_file_out != NULL)){
-+ printk("Failed to read COW header from COW file \"%s\", "
-+ "errno = %d\n", file, -err);
-+ goto out_close;
-+ }
-+ if(err) return(fd);
-+
-+ if(backing_file_out == NULL) return(fd);
-+
-+ same = same_backing_files(*backing_file_out, backing_file, file);
-+
-+ if(!same && !backing_file_mismatch(*backing_file_out, size, mtime)){
-+ printk("Switching backing file to '%s'\n", *backing_file_out);
-+ err = write_cow_header(file, fd, *backing_file_out,
-+ sectorsize, align, &size);
-+ if(err){
-+ printk("Switch failed, errno = %d\n", -err);
-+ return(err);
-+ }
-+ }
-+ else {
-+ *backing_file_out = backing_file;
-+ err = backing_file_mismatch(*backing_file_out, size, mtime);
-+ if(err) goto out_close;
-+ }
-+
-+ cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
-+ bitmap_len_out, data_offset_out);
-+
-+ return(fd);
-+ out_close:
-+ os_close_file(fd);
-+ return(err);
-+}
-+
-+int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
-+ int sectorsize, int alignment, int *bitmap_offset_out,
-+ unsigned long *bitmap_len_out, int *data_offset_out)
-+{
-+ int err, fd;
-+
-+ flags.c = 1;
-+ fd = open_ubd_file(cow_file, &flags, NULL, NULL, NULL, NULL, NULL);
-+ if(fd < 0){
-+ err = fd;
-+ printk("Open of COW file '%s' failed, errno = %d\n", cow_file,
-+ -err);
-+ goto out;
-+ }
-+
-+ err = init_cow_file(fd, cow_file, backing_file, sectorsize, alignment,
-+ bitmap_offset_out, bitmap_len_out,
-+ data_offset_out);
-+ if(!err)
-+ return(fd);
-+
-+ os_close_file(fd);
-+ out:
-+ return(err);
-+}
-+
-+/* XXX Just trivial wrappers around os_read_file and os_write_file */
-+int read_ubd_fs(int fd, void *buffer, int len)
-+{
-+ return(os_read_file(fd, buffer, len));
-+}
-+
-+int write_ubd_fs(int fd, char *buffer, int len)
-+{
-+ return(os_write_file(fd, buffer, len));
-+}
-+
-+static int update_bitmap(struct io_thread_req *req)
-+{
-+ int n;
-+
-+ if(req->cow_offset == -1)
-+ return(0);
-+
-+ n = os_seek_file(req->fds[1], req->cow_offset);
-+ if(n < 0){
-+ printk("do_io - bitmap lseek failed : err = %d\n", -n);
-+ return(1);
-+ }
-+
-+ n = os_write_file(req->fds[1], &req->bitmap_words,
-+ sizeof(req->bitmap_words));
-+ if(n != sizeof(req->bitmap_words)){
-+ printk("do_io - bitmap update failed, err = %d fd = %d\n", -n,
-+ req->fds[1]);
-+ return(1);
-+ }
-+
-+ return(0);
-+}
-+
-+void do_io(struct io_thread_req *req)
-+{
-+ char *buf;
-+ unsigned long len;
-+ int n, nsectors, start, end, bit;
-+ int err;
-+ __u64 off;
-+
-+ if(req->op == UBD_MMAP){
-+ /* Touch the page to force the host to do any necessary IO to
-+ * get it into memory
-+ */
-+ n = *((volatile int *) req->buffer);
-+ req->error = update_bitmap(req);
-+ return;
-+ }
-+
-+ nsectors = req->length / req->sectorsize;
-+ start = 0;
-+ do {
-+ bit = ubd_test_bit(start, (unsigned char *) &req->sector_mask);
-+ end = start;
-+ while((end < nsectors) &&
-+ (ubd_test_bit(end, (unsigned char *)
-+ &req->sector_mask) == bit))
-+ end++;
-+
-+ off = req->offset + req->offsets[bit] +
-+ start * req->sectorsize;
-+ len = (end - start) * req->sectorsize;
-+ buf = &req->buffer[start * req->sectorsize];
-+
-+ err = os_seek_file(req->fds[bit], off);
-+ if(err < 0){
-+ printk("do_io - lseek failed : err = %d\n", -err);
-+ req->error = 1;
-+ return;
-+ }
-+ if(req->op == UBD_READ){
-+ n = 0;
-+ do {
-+ buf = &buf[n];
-+ len -= n;
-+ n = os_read_file(req->fds[bit], buf, len);
-+ if (n < 0) {
-+ printk("do_io - read failed, err = %d "
-+ "fd = %d\n", -n, req->fds[bit]);
-+ req->error = 1;
-+ return;
-+ }
-+ } while((n < len) && (n != 0));
-+ if (n < len) memset(&buf[n], 0, len - n);
-+ }
-+ else {
-+ n = os_write_file(req->fds[bit], buf, len);
-+ if(n != len){
-+ printk("do_io - write failed err = %d "
-+ "fd = %d\n", -n, req->fds[bit]);
-+ req->error = 1;
-+ return;
-+ }
-+ }
-+
-+ start = end;
-+ } while(start < nsectors);
-+
-+ req->error = update_bitmap(req);
-+}
-+
-+/* Changed in start_io_thread, which is serialized by being called only
-+ * from ubd_init, which is an initcall.
-+ */
-+int kernel_fd = -1;
-+
-+/* Only changed by the io thread */
-+int io_count = 0;
-+
-+int io_thread(void *arg)
-+{
-+ struct io_thread_req req;
-+ int n;
-+
-+ signal(SIGWINCH, SIG_IGN);
-+ while(1){
-+ n = os_read_file(kernel_fd, &req, sizeof(req));
-+ if(n != sizeof(req)){
-+ if(n < 0)
-+ printk("io_thread - read failed, fd = %d, "
-+ "err = %d\n", kernel_fd, -n);
-+ else {
-+ printk("io_thread - short read, fd = %d, "
-+ "length = %d\n", kernel_fd, n);
-+ }
-+ continue;
-+ }
-+ io_count++;
-+ do_io(&req);
-+ n = os_write_file(kernel_fd, &req, sizeof(req));
-+ if(n != sizeof(req))
-+ printk("io_thread - write failed, fd = %d, err = %d\n",
-+ kernel_fd, -n);
-+ }
-+}
-+
-+int start_io_thread(unsigned long sp, int *fd_out)
-+{
-+ int pid, fds[2], err;
-+
-+ err = os_pipe(fds, 1, 1);
-+ if(err < 0){
-+ printk("start_io_thread - os_pipe failed, err = %d\n", -err);
-+ goto out;
-+ }
-+
-+ kernel_fd = fds[0];
-+ *fd_out = fds[1];
-+
-+ pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD,
-+ NULL);
-+ if(pid < 0){
-+ printk("start_io_thread - clone failed : errno = %d\n", errno);
-+ goto out_close;
-+ }
-+
-+ return(pid);
-+
-+ out_close:
-+ os_close_file(fds[0]);
-+ os_close_file(fds[1]);
-+ kernel_fd = -1;
-+ *fd_out = -1;
-+ out:
-+ return(err);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/xterm.c um/arch/um/drivers/xterm.c
---- orig/arch/um/drivers/xterm.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/xterm.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,201 @@
-+/*
-+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <string.h>
-+#include <errno.h>
-+#include <termios.h>
-+#include <signal.h>
-+#include <sched.h>
-+#include <sys/socket.h>
-+#include "kern_util.h"
-+#include "chan_user.h"
-+#include "helper.h"
-+#include "user_util.h"
-+#include "user.h"
-+#include "os.h"
-+#include "xterm.h"
-+
-+struct xterm_chan {
-+ int pid;
-+ int helper_pid;
-+ char *title;
-+ int device;
-+ int raw;
-+ struct termios tt;
-+ unsigned long stack;
-+ int direct_rcv;
-+};
-+
-+void *xterm_init(char *str, int device, struct chan_opts *opts)
-+{
-+ struct xterm_chan *data;
-+
-+ data = malloc(sizeof(*data));
-+ if(data == NULL) return(NULL);
-+ *data = ((struct xterm_chan) { .pid = -1,
-+ .helper_pid = -1,
-+ .device = device,
-+ .title = opts->xterm_title,
-+ .raw = opts->raw,
-+ .stack = opts->tramp_stack,
-+ .direct_rcv = !opts->in_kernel } );
-+ return(data);
-+}
-+
-+/* Only changed by xterm_setup, which is a setup */
-+static char *terminal_emulator = "xterm";
-+static char *title_switch = "-T";
-+static char *exec_switch = "-e";
-+
-+static int __init xterm_setup(char *line, int *add)
-+{
-+ *add = 0;
-+ terminal_emulator = line;
-+
-+ line = strchr(line, ',');
-+ if(line == NULL) return(0);
-+ *line++ = '\0';
-+ if(*line) title_switch = line;
-+
-+ line = strchr(line, ',');
-+ if(line == NULL) return(0);
-+ *line++ = '\0';
-+ if(*line) exec_switch = line;
-+
-+ return(0);
-+}
-+
-+__uml_setup("xterm=", xterm_setup,
-+"xterm=<terminal emulator>,<title switch>,<exec switch>\n"
-+" Specifies an alternate terminal emulator to use for the debugger,\n"
-+" consoles, and serial lines when they are attached to the xterm channel.\n"
-+" The values are the terminal emulator binary, the switch it uses to set\n"
-+" its title, and the switch it uses to execute a subprocess,\n"
-+" respectively. The title switch must have the form '<switch> title',\n"
-+" not '<switch>=title'. Similarly, the exec switch must have the form\n"
-+" '<switch> command arg1 arg2 ...'.\n"
-+" The default values are 'xterm=xterm,-T,-e'. Values for gnome-terminal\n"
-+" are 'xterm=gnome-terminal,-t,-x'.\n\n"
-+);
-+
-+int xterm_open(int input, int output, int primary, void *d, char **dev_out)
-+{
-+ struct xterm_chan *data = d;
-+ unsigned long stack;
-+ int pid, fd, new, err;
-+ char title[256], file[] = "/tmp/xterm-pipeXXXXXX";
-+ char *argv[] = { terminal_emulator, title_switch, title, exec_switch,
-+ "/usr/lib/uml/port-helper", "-uml-socket",
-+ file, NULL };
-+
-+ if(os_access(argv[4], OS_ACC_X_OK) < 0)
-+ argv[4] = "port-helper";
-+
-+ fd = mkstemp(file);
-+ if(fd < 0){
-+ printk("xterm_open : mkstemp failed, errno = %d\n", errno);
-+ return(-errno);
-+ }
-+
-+ if(unlink(file)){
-+ printk("xterm_open : unlink failed, errno = %d\n", errno);
-+ return(-errno);
-+ }
-+ os_close_file(fd);
-+
-+ fd = os_create_unix_socket(file, sizeof(file), 1);
-+ if(fd < 0){
-+ printk("xterm_open : create_unix_socket failed, errno = %d\n",
-+ -fd);
-+ return(fd);
-+ }
-+
-+ sprintf(title, data->title, data->device);
-+ stack = data->stack;
-+ pid = run_helper(NULL, NULL, argv, &stack);
-+ if(pid < 0){
-+ printk("xterm_open : run_helper failed, errno = %d\n", -pid);
-+ return(pid);
-+ }
-+
-+ if(data->stack == 0) free_stack(stack, 0);
-+
-+ if(data->direct_rcv)
-+ new = os_rcv_fd(fd, &data->helper_pid);
-+ else {
-+ err = os_set_fd_block(fd, 0);
-+ if(err < 0){
-+ printk("xterm_open : failed to set descriptor "
-+ "non-blocking, err = %d\n", -err);
-+ return(err);
-+ }
-+ new = xterm_fd(fd, &data->helper_pid);
-+ }
-+ if(new < 0){
-+ printk("xterm_open : os_rcv_fd failed, err = %d\n", -new);
-+ goto out;
-+ }
-+
-+ tcgetattr(new, &data->tt);
-+ if(data->raw) raw(new, 0);
-+
-+ data->pid = pid;
-+ *dev_out = NULL;
-+ out:
-+ unlink(file);
-+ return(new);
-+}
-+
-+void xterm_close(int fd, void *d)
-+{
-+ struct xterm_chan *data = d;
-+
-+ if(data->pid != -1)
-+ os_kill_process(data->pid, 1);
-+ data->pid = -1;
-+ if(data->helper_pid != -1)
-+ os_kill_process(data->helper_pid, 0);
-+ data->helper_pid = -1;
-+ os_close_file(fd);
-+}
-+
-+void xterm_free(void *d)
-+{
-+ free(d);
-+}
-+
-+int xterm_console_write(int fd, const char *buf, int n, void *d)
-+{
-+ struct xterm_chan *data = d;
-+
-+ return(generic_console_write(fd, buf, n, &data->tt));
-+}
-+
-+struct chan_ops xterm_ops = {
-+ .type = "xterm",
-+ .init = xterm_init,
-+ .open = xterm_open,
-+ .close = xterm_close,
-+ .read = generic_read,
-+ .write = generic_write,
-+ .console_write = xterm_console_write,
-+ .window_size = generic_window_size,
-+ .free = xterm_free,
-+ .winch = 1,
-+};
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/xterm.h um/arch/um/drivers/xterm.h
---- orig/arch/um/drivers/xterm.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/xterm.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,22 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __XTERM_H__
-+#define __XTERM_H__
-+
-+extern int xterm_fd(int socket, int *pid_out);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/drivers/xterm_kern.c um/arch/um/drivers/xterm_kern.c
---- orig/arch/um/drivers/xterm_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/drivers/xterm_kern.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,82 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/errno.h"
-+#include "linux/slab.h"
-+#include "asm/semaphore.h"
-+#include "asm/irq.h"
-+#include "irq_user.h"
-+#include "irq_kern.h"
-+#include "kern_util.h"
-+#include "os.h"
-+#include "xterm.h"
-+
-+struct xterm_wait {
-+ struct semaphore sem;
-+ int fd;
-+ int pid;
-+ int new_fd;
-+};
-+
-+static void xterm_interrupt(int irq, void *data, struct pt_regs *regs)
-+{
-+ struct xterm_wait *xterm = data;
-+ int fd;
-+
-+ fd = os_rcv_fd(xterm->fd, &xterm->pid);
-+ if(fd == -EAGAIN)
-+ return;
-+
-+ xterm->new_fd = fd;
-+ up(&xterm->sem);
-+}
-+
-+int xterm_fd(int socket, int *pid_out)
-+{
-+ struct xterm_wait *data;
-+ int err, ret;
-+
-+ data = kmalloc(sizeof(*data), GFP_KERNEL);
-+ if(data == NULL){
-+ printk(KERN_ERR "xterm_fd : failed to allocate xterm_wait\n");
-+ return(-ENOMEM);
-+ }
-+ *data = ((struct xterm_wait)
-+ { .sem = __SEMAPHORE_INITIALIZER(data->sem, 0),
-+ .fd = socket,
-+ .pid = -1,
-+ .new_fd = -1 });
-+
-+ err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt,
-+ SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
-+ "xterm", data);
-+ if(err){
-+ printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, "
-+ "err = %d\n", err);
-+ ret = err;
-+ goto out;
-+ }
-+ down(&data->sem);
-+
-+ free_irq(XTERM_IRQ, data);
-+
-+ ret = data->new_fd;
-+ *pid_out = data->pid;
-+ out:
-+ kfree(data);
-+
-+ return(ret);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/dyn_link.ld.in um/arch/um/dyn_link.ld.in
---- orig/arch/um/dyn_link.ld.in 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/dyn_link.ld.in 2004-01-10 04:28:44.000000000 -0500
-@@ -0,0 +1,171 @@
-+OUTPUT_FORMAT("ELF_FORMAT")
-+OUTPUT_ARCH(ELF_ARCH)
-+ENTRY(_start)
-+SEARCH_DIR("/usr/local/i686-pc-linux-gnu/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");
-+/* Do we need any of these for elf?
-+ __DYNAMIC = 0; */
-+SECTIONS
-+{
-+ . = START() + SIZEOF_HEADERS;
-+ .interp : { *(.interp) }
-+ __binary_start = .;
-+ . = ALIGN(4096); /* Init code and data */
-+ _stext = .;
-+ __init_begin = .;
-+ .text.init : { *(.text.init) }
-+
-+ . = ALIGN(4096);
-+
-+ /* Read-only sections, merged into text segment: */
-+ .hash : { *(.hash) }
-+ .dynsym : { *(.dynsym) }
-+ .dynstr : { *(.dynstr) }
-+ .gnu.version : { *(.gnu.version) }
-+ .gnu.version_d : { *(.gnu.version_d) }
-+ .gnu.version_r : { *(.gnu.version_r) }
-+ .rel.init : { *(.rel.init) }
-+ .rela.init : { *(.rela.init) }
-+ .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
-+ .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
-+ .rel.fini : { *(.rel.fini) }
-+ .rela.fini : { *(.rela.fini) }
-+ .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
-+ .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
-+ .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
-+ .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
-+ .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
-+ .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
-+ .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
-+ .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
-+ .rel.ctors : { *(.rel.ctors) }
-+ .rela.ctors : { *(.rela.ctors) }
-+ .rel.dtors : { *(.rel.dtors) }
-+ .rela.dtors : { *(.rela.dtors) }
-+ .rel.got : { *(.rel.got) }
-+ .rela.got : { *(.rela.got) }
-+ .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
-+ .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
-+ .rel.plt : { *(.rel.plt) }
-+ .rela.plt : { *(.rela.plt) }
-+ .init : {
-+ KEEP (*(.init))
-+ } =0x90909090
-+ .plt : { *(.plt) }
-+ .text : {
-+ *(.text .stub .text.* .gnu.linkonce.t.*)
-+ /* .gnu.warning sections are handled specially by elf32.em. */
-+ *(.gnu.warning)
-+ } =0x90909090
-+ .fini : {
-+ KEEP (*(.fini))
-+ } =0x90909090
-+
-+ PROVIDE (__etext = .);
-+ PROVIDE (_etext = .);
-+ PROVIDE (etext = .);
-+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
-+ .rodata1 : { *(.rodata1) }
-+ .eh_frame_hdr : { *(.eh_frame_hdr) }
-+
-+
-+ . = ALIGN(4096);
-+ PROVIDE (_sdata = .);
-+
-+include(`arch/um/common.ld.in')
-+
-+ /* Ensure the __preinit_array_start label is properly aligned. We
-+ could instead move the label definition inside the section, but
-+ the linker would then create the section even if it turns out to
-+ be empty, which isn't pretty. */
-+ . = ALIGN(32 / 8);
-+ .preinit_array : { *(.preinit_array) }
-+ .init_array : { *(.init_array) }
-+ .fini_array : { *(.fini_array) }
-+ .data : {
-+ . = ALIGN(KERNEL_STACK_SIZE); /* init_task */
-+ *(.data.init_task)
-+ *(.data .data.* .gnu.linkonce.d.*)
-+ SORT(CONSTRUCTORS)
-+ }
-+ .data1 : { *(.data1) }
-+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
-+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
-+ .eh_frame : { KEEP (*(.eh_frame)) }
-+ .gcc_except_table : { *(.gcc_except_table) }
-+ .dynamic : { *(.dynamic) }
-+ .ctors : {
-+ /* gcc uses crtbegin.o to find the start of
-+ the constructors, so we make sure it is
-+ first. Because this is a wildcard, it
-+ doesn't matter if the user does not
-+ actually link against crtbegin.o; the
-+ linker won't look for a file to match a
-+ wildcard. The wildcard also means that it
-+ doesn't matter which directory crtbegin.o
-+ is in. */
-+ KEEP (*crtbegin.o(.ctors))
-+ /* We don't want to include the .ctor section from
-+ from the crtend.o file until after the sorted ctors.
-+ The .ctor section from the crtend file contains the
-+ end of ctors marker and it must be last */
-+ KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
-+ KEEP (*(SORT(.ctors.*)))
-+ KEEP (*(.ctors))
-+ }
-+ .dtors : {
-+ KEEP (*crtbegin.o(.dtors))
-+ KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
-+ KEEP (*(SORT(.dtors.*)))
-+ KEEP (*(.dtors))
-+ }
-+ .jcr : { KEEP (*(.jcr)) }
-+ .got : { *(.got.plt) *(.got) }
-+ _edata = .;
-+ PROVIDE (edata = .);
-+ __bss_start = .;
-+ .bss : {
-+ *(.dynbss)
-+ *(.bss .bss.* .gnu.linkonce.b.*)
-+ *(COMMON)
-+ /* Align here to ensure that the .bss section occupies space up to
-+ _end. Align after .bss to ensure correct alignment even if the
-+ .bss section disappears because there are no input sections. */
-+ . = ALIGN(32 / 8);
-+ . = ALIGN(32 / 8);
-+ }
-+ _end = .;
-+ PROVIDE (end = .);
-+ /* Stabs debugging sections. */
-+ .stab 0 : { *(.stab) }
-+ .stabstr 0 : { *(.stabstr) }
-+ .stab.excl 0 : { *(.stab.excl) }
-+ .stab.exclstr 0 : { *(.stab.exclstr) }
-+ .stab.index 0 : { *(.stab.index) }
-+ .stab.indexstr 0 : { *(.stab.indexstr) }
-+ .comment 0 : { *(.comment) }
-+ /* DWARF debug sections.
-+ Symbols in the DWARF debugging sections are relative to the beginning
-+ of the section so we begin them at 0. */
-+ /* DWARF 1 */
-+ .debug 0 : { *(.debug) }
-+ .line 0 : { *(.line) }
-+ /* GNU DWARF 1 extensions */
-+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
-+ .debug_sfnames 0 : { *(.debug_sfnames) }
-+ /* DWARF 1.1 and DWARF 2 */
-+ .debug_aranges 0 : { *(.debug_aranges) }
-+ .debug_pubnames 0 : { *(.debug_pubnames) }
-+ /* DWARF 2 */
-+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
-+ .debug_abbrev 0 : { *(.debug_abbrev) }
-+ .debug_line 0 : { *(.debug_line) }
-+ .debug_frame 0 : { *(.debug_frame) }
-+ .debug_str 0 : { *(.debug_str) }
-+ .debug_loc 0 : { *(.debug_loc) }
-+ .debug_macinfo 0 : { *(.debug_macinfo) }
-+ /* SGI/MIPS DWARF 2 extensions */
-+ .debug_weaknames 0 : { *(.debug_weaknames) }
-+ .debug_funcnames 0 : { *(.debug_funcnames) }
-+ .debug_typenames 0 : { *(.debug_typenames) }
-+ .debug_varnames 0 : { *(.debug_varnames) }
-+}
-diff -Naur -X ../exclude-files orig/arch/um/fs/hostfs/hostfs.h um/arch/um/fs/hostfs/hostfs.h
---- orig/arch/um/fs/hostfs/hostfs.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/fs/hostfs/hostfs.h 2003-12-17 10:52:50.000000000 -0500
-@@ -0,0 +1,69 @@
-+#ifndef __UM_FS_HOSTFS
-+#define __UM_FS_HOSTFS
-+
-+#include "os.h"
-+
-+/* These are exactly the same definitions as in fs.h, but the names are
-+ * changed so that this file can be included in both kernel and user files.
-+ */
-+
-+#define HOSTFS_ATTR_MODE 1
-+#define HOSTFS_ATTR_UID 2
-+#define HOSTFS_ATTR_GID 4
-+#define HOSTFS_ATTR_SIZE 8
-+#define HOSTFS_ATTR_ATIME 16
-+#define HOSTFS_ATTR_MTIME 32
-+#define HOSTFS_ATTR_CTIME 64
-+#define HOSTFS_ATTR_ATIME_SET 128
-+#define HOSTFS_ATTR_MTIME_SET 256
-+#define HOSTFS_ATTR_FORCE 512 /* Not a change, but a change it */
-+#define HOSTFS_ATTR_ATTR_FLAG 1024
-+
-+struct hostfs_iattr {
-+ unsigned int ia_valid;
-+ mode_t ia_mode;
-+ uid_t ia_uid;
-+ gid_t ia_gid;
-+ loff_t ia_size;
-+ time_t ia_atime;
-+ time_t ia_mtime;
-+ time_t ia_ctime;
-+ unsigned int ia_attr_flags;
-+};
-+
-+extern int stat_file(const char *path, int *dev_out,
-+ unsigned long long *inode_out, int *mode_out,
-+ int *nlink_out, int *uid_out, int *gid_out,
-+ unsigned long long *size_out, unsigned long *atime_out,
-+ unsigned long *mtime_out, unsigned long *ctime_out,
-+ int *blksize_out, unsigned long long *blocks_out);
-+extern int access_file(char *path, int r, int w, int x);
-+extern int open_file(char *path, int r, int w, int append);
-+extern int file_type(const char *path, int *rdev);
-+extern void *open_dir(char *path, int *err_out);
-+extern char *read_dir(void *stream, unsigned long long *pos,
-+ unsigned long long *ino_out, int *len_out);
-+extern void close_file(void *stream);
-+extern void close_dir(void *stream);
-+extern int read_file(int fd, unsigned long long *offset, char *buf, int len);
-+extern int write_file(int fd, unsigned long long *offset, const char *buf,
-+ int len);
-+extern int lseek_file(int fd, long long offset, int whence);
-+extern int file_create(char *name, int ur, int uw, int ux, int gr,
-+ int gw, int gx, int or, int ow, int ox);
-+extern int set_attr(const char *file, struct hostfs_iattr *attrs);
-+extern int make_symlink(const char *from, const char *to);
-+extern int unlink_file(const char *file);
-+extern int do_mkdir(const char *file, int mode);
-+extern int do_rmdir(const char *file);
-+extern int do_mknod(const char *file, int mode, int dev);
-+extern int link_file(const char *from, const char *to);
-+extern int do_readlink(char *file, char *buf, int size);
-+extern int rename_file(char *from, char *to);
-+extern int do_statfs(char *root, long *bsize_out, long long *blocks_out,
-+ long long *bfree_out, long long *bavail_out,
-+ long long *files_out, long long *ffree_out,
-+ void *fsid_out, int fsid_size, long *namelen_out,
-+ long *spare_out);
-+
-+#endif
-diff -Naur -X ../exclude-files orig/arch/um/fs/hostfs/hostfs_kern.c um/arch/um/fs/hostfs/hostfs_kern.c
---- orig/arch/um/fs/hostfs/hostfs_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/fs/hostfs/hostfs_kern.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,965 @@
-+/*
-+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <linux/stddef.h>
-+#include <linux/fs.h>
-+#include <linux/version.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/slab.h>
-+#include <linux/pagemap.h>
-+#include <linux/blkdev.h>
-+#include <asm/uaccess.h>
-+#include "hostfs.h"
-+#include "kern_util.h"
-+#include "kern.h"
-+#include "user_util.h"
-+#include "2_5compat.h"
-+#include "init.h"
-+
-+#define file_hostfs_i(file) (&(file)->f_dentry->d_inode->u.hostfs_i)
-+
-+int hostfs_d_delete(struct dentry *dentry)
-+{
-+ return(1);
-+}
-+
-+struct dentry_operations hostfs_dentry_ops = {
-+ .d_delete = hostfs_d_delete,
-+};
-+
-+#define DEFAULT_ROOT "/"
-+
-+/* Changed in hostfs_args before the kernel starts running */
-+static char *jail_dir = NULL;
-+static int append = 0;
-+
-+#define HOSTFS_SUPER_MAGIC 0x00c0ffee
-+
-+static struct inode_operations hostfs_iops;
-+static struct inode_operations hostfs_dir_iops;
-+static struct address_space_operations hostfs_link_aops;
-+
-+static int __init hostfs_args(char *options, int *add)
-+{
-+ char *ptr;
-+
-+ ptr = strchr(options, ',');
-+ if(ptr != NULL)
-+ *ptr++ = '\0';
-+ if(*options != '\0')
-+ jail_dir = options;
-+
-+ options = ptr;
-+ while(options){
-+ ptr = strchr(options, ',');
-+ if(ptr != NULL)
-+ *ptr++ = '\0';
-+ if(*options != '\0'){
-+ if(!strcmp(options, "append"))
-+ append = 1;
-+ else printf("hostfs_args - unsupported option - %s\n",
-+ options);
-+ }
-+ options = ptr;
-+ }
-+ return(0);
-+}
-+
-+__uml_setup("hostfs=", hostfs_args,
-+"hostfs=<root dir>,<flags>,...\n"
-+" This is used to set hostfs parameters. The root directory argument\n"
-+" is used to confine all hostfs mounts to within the specified directory\n"
-+" tree on the host. If this isn't specified, then a user inside UML can\n"
-+" mount anything on the host that's accessible to the user that's running\n"
-+" it.\n"
-+" The only flag currently supported is 'append', which specifies that all\n"
-+" files opened by hostfs will be opened in append mode.\n\n"
-+);
-+
-+static char *dentry_name(struct dentry *dentry, int extra)
-+{
-+ struct dentry *parent;
-+ char *root, *name;
-+ int len;
-+
-+ len = 0;
-+ parent = dentry;
-+ while(parent->d_parent != parent){
-+ len += parent->d_name.len + 1;
-+ parent = parent->d_parent;
-+ }
-+
-+ root = parent->d_inode->u.hostfs_i.host_filename;
-+ len += strlen(root);
-+ name = kmalloc(len + extra + 1, GFP_KERNEL);
-+ if(name == NULL) return(NULL);
-+
-+ name[len] = '\0';
-+ parent = dentry;
-+ while(parent->d_parent != parent){
-+ len -= parent->d_name.len + 1;
-+ name[len] = '/';
-+ strncpy(&name[len + 1], parent->d_name.name,
-+ parent->d_name.len);
-+ parent = parent->d_parent;
-+ }
-+ strncpy(name, root, strlen(root));
-+ return(name);
-+}
-+
-+static char *inode_name(struct inode *ino, int extra)
-+{
-+ struct dentry *dentry;
-+
-+ dentry = list_entry(ino->i_dentry.next, struct dentry, d_alias);
-+ return(dentry_name(dentry, extra));
-+}
-+
-+static int read_name(struct inode *ino, char *name)
-+{
-+ /* The non-int inode fields are copied into ints by stat_file and
-+ * then copied into the inode because passing the actual pointers
-+ * in and having them treated as int * breaks on big-endian machines
-+ */
-+ int err;
-+ int i_dev, i_mode, i_nlink, i_blksize;
-+ unsigned long long i_size;
-+ unsigned long long i_ino;
-+ unsigned long long i_blocks;
-+ err = stat_file(name, &i_dev, &i_ino, &i_mode, &i_nlink,
-+ &ino->i_uid, &ino->i_gid, &i_size, &ino->i_atime,
-+ &ino->i_mtime, &ino->i_ctime, &i_blksize, &i_blocks);
-+ if(err) return(err);
-+ ino->i_ino = i_ino;
-+ ino->i_dev = i_dev;
-+ ino->i_mode = i_mode;
-+ ino->i_nlink = i_nlink;
-+ ino->i_size = i_size;
-+ ino->i_blksize = i_blksize;
-+ ino->i_blocks = i_blocks;
-+ if(kdev_same(ino->i_sb->s_dev, ROOT_DEV) && (ino->i_uid == getuid()))
-+ ino->i_uid = 0;
-+ return(0);
-+}
-+
-+static char *follow_link(char *link)
-+{
-+ int len, n;
-+ char *name, *resolved, *end;
-+
-+ len = 64;
-+ while(1){
-+ n = -ENOMEM;
-+ name = kmalloc(len, GFP_KERNEL);
-+ if(name == NULL)
-+ goto out;
-+
-+ n = do_readlink(link, name, len);
-+ if(n < len)
-+ break;
-+ len *= 2;
-+ kfree(name);
-+ }
-+ if(n < 0)
-+ goto out_free;
-+
-+ if(*name == '/')
-+ return(name);
-+
-+ end = strrchr(link, '/');
-+ if(end == NULL)
-+ return(name);
-+
-+ *(end + 1) = '\0';
-+ len = strlen(link) + strlen(name) + 1;
-+
-+ resolved = kmalloc(len, GFP_KERNEL);
-+ if(resolved == NULL){
-+ n = -ENOMEM;
-+ goto out_free;
-+ }
-+
-+ sprintf(resolved, "%s%s", link, name);
-+ kfree(name);
-+ kfree(link);
-+ return(resolved);
-+
-+ out_free:
-+ kfree(name);
-+ out:
-+ return(ERR_PTR(n));
-+}
-+
-+static int read_inode(struct inode *ino)
-+{
-+ char *name;
-+ int err;
-+
-+ err = -ENOMEM;
-+ name = inode_name(ino, 0);
-+ if(name == NULL)
-+ goto out;
-+
-+ if(file_type(name, NULL) == OS_TYPE_SYMLINK){
-+ name = follow_link(name);
-+ if(IS_ERR(name)){
-+ err = PTR_ERR(name);
-+ goto out;
-+ }
-+ }
-+
-+ err = read_name(ino, name);
-+ kfree(name);
-+ out:
-+ return(err);
-+}
-+
-+void hostfs_delete_inode(struct inode *ino)
-+{
-+ if(ino->u.hostfs_i.host_filename)
-+ kfree(ino->u.hostfs_i.host_filename);
-+ ino->u.hostfs_i.host_filename = NULL;
-+
-+ if(ino->u.hostfs_i.fd != -1)
-+ close_file(&ino->u.hostfs_i.fd);
-+
-+ ino->u.hostfs_i.mode = 0;
-+ clear_inode(ino);
-+}
-+
-+int hostfs_statfs(struct super_block *sb, struct statfs *sf)
-+{
-+ /* do_statfs uses struct statfs64 internally, but the linux kernel
-+ * struct statfs still has 32-bit versions for most of these fields,
-+ * so we convert them here
-+ */
-+ int err;
-+ long long f_blocks;
-+ long long f_bfree;
-+ long long f_bavail;
-+ long long f_files;
-+ long long f_ffree;
-+
-+ err = do_statfs(sb->s_root->d_inode->u.hostfs_i.host_filename,
-+ &sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files,
-+ &f_ffree, &sf->f_fsid, sizeof(sf->f_fsid),
-+ &sf->f_namelen, sf->f_spare);
-+ if(err) return(err);
-+ sf->f_blocks = f_blocks;
-+ sf->f_bfree = f_bfree;
-+ sf->f_bavail = f_bavail;
-+ sf->f_files = f_files;
-+ sf->f_ffree = f_ffree;
-+ sf->f_type = HOSTFS_SUPER_MAGIC;
-+ return(0);
-+}
-+
-+static struct super_operations hostfs_sbops = {
-+ .put_inode = force_delete,
-+ .delete_inode = hostfs_delete_inode,
-+ .statfs = hostfs_statfs,
-+};
-+
-+int hostfs_readdir(struct file *file, void *ent, filldir_t filldir)
-+{
-+ void *dir;
-+ char *name;
-+ unsigned long long next, ino;
-+ int error, len;
-+
-+ name = dentry_name(file->f_dentry, 0);
-+ if(name == NULL) return(-ENOMEM);
-+ dir = open_dir(name, &error);
-+ kfree(name);
-+ if(dir == NULL) return(-error);
-+ next = file->f_pos;
-+ while((name = read_dir(dir, &next, &ino, &len)) != NULL){
-+ error = (*filldir)(ent, name, len, file->f_pos,
-+ ino, DT_UNKNOWN);
-+ if(error) break;
-+ file->f_pos = next;
-+ }
-+ close_dir(dir);
-+ return(0);
-+}
-+
-+int hostfs_file_open(struct inode *ino, struct file *file)
-+{
-+ char *name;
-+ int mode = 0, r = 0, w = 0, fd;
-+
-+ mode = file->f_mode & (FMODE_READ | FMODE_WRITE);
-+ if((mode & ino->u.hostfs_i.mode) == mode)
-+ return(0);
-+
-+ /* The file may already have been opened, but with the wrong access,
-+ * so this resets things and reopens the file with the new access.
-+ */
-+ if(ino->u.hostfs_i.fd != -1){
-+ close_file(&ino->u.hostfs_i.fd);
-+ ino->u.hostfs_i.fd = -1;
-+ }
-+
-+ ino->u.hostfs_i.mode |= mode;
-+ if(ino->u.hostfs_i.mode & FMODE_READ)
-+ r = 1;
-+ if(ino->u.hostfs_i.mode & FMODE_WRITE)
-+ w = 1;
-+ if(w)
-+ r = 1;
-+
-+ name = dentry_name(file->f_dentry, 0);
-+ if(name == NULL)
-+ return(-ENOMEM);
-+
-+ fd = open_file(name, r, w, append);
-+ kfree(name);
-+ if(fd < 0) return(fd);
-+ file_hostfs_i(file)->fd = fd;
-+
-+ return(0);
-+}
-+
-+int hostfs_dir_open(struct inode *ino, struct file *file)
-+{
-+ return(0);
-+}
-+
-+int hostfs_dir_release(struct inode *ino, struct file *file)
-+{
-+ return(0);
-+}
-+
-+int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync)
-+{
-+ return(0);
-+}
-+
-+static struct file_operations hostfs_file_fops = {
-+ .owner = NULL,
-+ .read = generic_file_read,
-+ .write = generic_file_write,
-+ .mmap = generic_file_mmap,
-+ .open = hostfs_file_open,
-+ .release = NULL,
-+ .fsync = hostfs_fsync,
-+};
-+
-+static struct file_operations hostfs_dir_fops = {
-+ .owner = NULL,
-+ .readdir = hostfs_readdir,
-+ .open = hostfs_dir_open,
-+ .release = hostfs_dir_release,
-+ .fsync = hostfs_fsync,
-+};
-+
-+int hostfs_writepage(struct page *page)
-+{
-+ struct address_space *mapping = page->mapping;
-+ struct inode *inode = mapping->host;
-+ char *buffer;
-+ unsigned long long base;
-+ int count = PAGE_CACHE_SIZE;
-+ int end_index = inode->i_size >> PAGE_CACHE_SHIFT;
-+ int err;
-+
-+ if (page->index >= end_index)
-+ count = inode->i_size & (PAGE_CACHE_SIZE-1);
-+
-+ buffer = kmap(page);
-+ base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT;
-+
-+ err = write_file(inode->u.hostfs_i.fd, &base, buffer, count);
-+ if(err != count){
-+ ClearPageUptodate(page);
-+ goto out;
-+ }
-+
-+ if (base > inode->i_size)
-+ inode->i_size = base;
-+
-+ if (PageError(page))
-+ ClearPageError(page);
-+ err = 0;
-+
-+ out:
-+ kunmap(page);
-+
-+ UnlockPage(page);
-+ return err;
-+}
-+
-+int hostfs_readpage(struct file *file, struct page *page)
-+{
-+ char *buffer;
-+ long long start;
-+ int err = 0;
-+
-+ start = (long long) page->index << PAGE_CACHE_SHIFT;
-+ buffer = kmap(page);
-+ err = read_file(file_hostfs_i(file)->fd, &start, buffer,
-+ PAGE_CACHE_SIZE);
-+ if(err < 0) goto out;
-+
-+ memset(&buffer[err], 0, PAGE_CACHE_SIZE - err);
-+
-+ flush_dcache_page(page);
-+ SetPageUptodate(page);
-+ if (PageError(page)) ClearPageError(page);
-+ err = 0;
-+ out:
-+ kunmap(page);
-+ UnlockPage(page);
-+ return(err);
-+}
-+
-+int hostfs_prepare_write(struct file *file, struct page *page,
-+ unsigned int from, unsigned int to)
-+{
-+ char *buffer;
-+ long long start, tmp;
-+ int err;
-+
-+ start = (long long) page->index << PAGE_CACHE_SHIFT;
-+ buffer = kmap(page);
-+ if(from != 0){
-+ tmp = start;
-+ err = read_file(file_hostfs_i(file)->fd, &tmp, buffer,
-+ from);
-+ if(err < 0) goto out;
-+ }
-+ if(to != PAGE_CACHE_SIZE){
-+ start += to;
-+ err = read_file(file_hostfs_i(file)->fd, &start, buffer + to,
-+ PAGE_CACHE_SIZE - to);
-+ if(err < 0) goto out;
-+ }
-+ err = 0;
-+ out:
-+ kunmap(page);
-+ return(err);
-+}
-+
-+int hostfs_commit_write(struct file *file, struct page *page, unsigned from,
-+ unsigned to)
-+{
-+ struct address_space *mapping = page->mapping;
-+ struct inode *inode = mapping->host;
-+ char *buffer;
-+ long long start;
-+ int err = 0;
-+
-+ start = (long long) (page->index << PAGE_CACHE_SHIFT) + from;
-+ buffer = kmap(page);
-+ err = write_file(file_hostfs_i(file)->fd, &start, buffer + from,
-+ to - from);
-+ if(err > 0) err = 0;
-+ if(!err && (start > inode->i_size))
-+ inode->i_size = start;
-+
-+ kunmap(page);
-+ return(err);
-+}
-+
-+static struct address_space_operations hostfs_aops = {
-+ .writepage = hostfs_writepage,
-+ .readpage = hostfs_readpage,
-+/* .set_page_dirty = __set_page_dirty_nobuffers, */
-+ .prepare_write = hostfs_prepare_write,
-+ .commit_write = hostfs_commit_write
-+};
-+
-+static struct inode *get_inode(struct super_block *sb, struct dentry *dentry,
-+ int *error)
-+{
-+ struct inode *inode;
-+ char *name;
-+ int type, err = -ENOMEM, rdev;
-+
-+ inode = new_inode(sb);
-+ if(inode == NULL)
-+ goto out;
-+
-+ inode->u.hostfs_i.host_filename = NULL;
-+ inode->u.hostfs_i.fd = -1;
-+ inode->u.hostfs_i.mode = 0;
-+ insert_inode_hash(inode);
-+ if(dentry){
-+ name = dentry_name(dentry, 0);
-+ if(name == NULL){
-+ err = -ENOMEM;
-+ goto out_put;
-+ }
-+ type = file_type(name, &rdev);
-+ kfree(name);
-+ }
-+ else type = OS_TYPE_DIR;
-+ inode->i_sb = sb;
-+
-+ err = 0;
-+ if(type == OS_TYPE_SYMLINK)
-+ inode->i_op = &page_symlink_inode_operations;
-+ else if(type == OS_TYPE_DIR)
-+ inode->i_op = &hostfs_dir_iops;
-+ else inode->i_op = &hostfs_iops;
-+
-+ if(type == OS_TYPE_DIR) inode->i_fop = &hostfs_dir_fops;
-+ else inode->i_fop = &hostfs_file_fops;
-+
-+ if(type == OS_TYPE_SYMLINK)
-+ inode->i_mapping->a_ops = &hostfs_link_aops;
-+ else inode->i_mapping->a_ops = &hostfs_aops;
-+
-+ switch (type) {
-+ case OS_TYPE_CHARDEV:
-+ init_special_inode(inode, S_IFCHR, rdev);
-+ break;
-+ case OS_TYPE_BLOCKDEV:
-+ init_special_inode(inode, S_IFBLK, rdev);
-+ break;
-+ case OS_TYPE_FIFO:
-+ init_special_inode(inode, S_IFIFO, 0);
-+ break;
-+ case OS_TYPE_SOCK:
-+ init_special_inode(inode, S_IFSOCK, 0);
-+ break;
-+ }
-+
-+ if(error) *error = err;
-+ return(inode);
-+ out_put:
-+ make_bad_inode(inode);
-+ iput(inode);
-+ out:
-+ if(error) *error = err;
-+ return(NULL);
-+}
-+
-+int hostfs_create(struct inode *dir, struct dentry *dentry, int mode)
-+{
-+ struct inode *inode;
-+ char *name;
-+ int error, fd;
-+
-+ inode = get_inode(dir->i_sb, dentry, &error);
-+ if(error) return(error);
-+ name = dentry_name(dentry, 0);
-+ if(name == NULL){
-+ iput(inode);
-+ return(-ENOMEM);
-+ }
-+ fd = file_create(name,
-+ mode & S_IRUSR, mode & S_IWUSR, mode & S_IXUSR,
-+ mode & S_IRGRP, mode & S_IWGRP, mode & S_IXGRP,
-+ mode & S_IROTH, mode & S_IWOTH, mode & S_IXOTH);
-+ if(fd < 0)
-+ error = fd;
-+ else error = read_name(inode, name);
-+
-+ kfree(name);
-+ if(error){
-+ iput(inode);
-+ return(error);
-+ }
-+ inode->u.hostfs_i.fd = fd;
-+ inode->u.hostfs_i.mode = FMODE_READ | FMODE_WRITE;
-+ d_instantiate(dentry, inode);
-+ return(0);
-+}
-+
-+struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry)
-+{
-+ struct inode *inode;
-+ char *name;
-+ int error;
-+
-+ inode = get_inode(ino->i_sb, dentry, &error);
-+ if(error != 0) return(ERR_PTR(error));
-+ name = dentry_name(dentry, 0);
-+ if(name == NULL) return(ERR_PTR(-ENOMEM));
-+ error = read_name(inode, name);
-+ kfree(name);
-+ if(error){
-+ iput(inode);
-+ if(error == -ENOENT) inode = NULL;
-+ else return(ERR_PTR(error));
-+ }
-+ d_add(dentry, inode);
-+ dentry->d_op = &hostfs_dentry_ops;
-+ return(NULL);
-+}
-+
-+static char *inode_dentry_name(struct inode *ino, struct dentry *dentry)
-+{
-+ char *file;
-+ int len;
-+
-+ file = inode_name(ino, dentry->d_name.len + 1);
-+ if(file == NULL) return(NULL);
-+ strcat(file, "/");
-+ len = strlen(file);
-+ strncat(file, dentry->d_name.name, dentry->d_name.len);
-+ file[len + dentry->d_name.len] = '\0';
-+ return(file);
-+}
-+
-+int hostfs_link(struct dentry *to, struct inode *ino, struct dentry *from)
-+{
-+ char *from_name, *to_name;
-+ int err;
-+
-+ from_name = inode_dentry_name(ino, from);
-+ if(from_name == NULL)
-+ return(-ENOMEM);
-+ to_name = dentry_name(to, 0);
-+ if(to_name == NULL){
-+ kfree(from_name);
-+ return(-ENOMEM);
-+ }
-+ err = link_file(to_name, from_name);
-+ kfree(from_name);
-+ kfree(to_name);
-+ return(err);
-+}
-+
-+int hostfs_unlink(struct inode *ino, struct dentry *dentry)
-+{
-+ char *file;
-+ int err;
-+
-+ file = inode_dentry_name(ino, dentry);
-+ if(file == NULL) return(-ENOMEM);
-+ if(append)
-+ return(-EPERM);
-+
-+ err = unlink_file(file);
-+ kfree(file);
-+ return(err);
-+}
-+
-+int hostfs_symlink(struct inode *ino, struct dentry *dentry, const char *to)
-+{
-+ char *file;
-+ int err;
-+
-+ file = inode_dentry_name(ino, dentry);
-+ if(file == NULL) return(-ENOMEM);
-+ err = make_symlink(file, to);
-+ kfree(file);
-+ return(err);
-+}
-+
-+int hostfs_mkdir(struct inode *ino, struct dentry *dentry, int mode)
-+{
-+ char *file;
-+ int err;
-+
-+ file = inode_dentry_name(ino, dentry);
-+ if(file == NULL) return(-ENOMEM);
-+ err = do_mkdir(file, mode);
-+ kfree(file);
-+ return(err);
-+}
-+
-+int hostfs_rmdir(struct inode *ino, struct dentry *dentry)
-+{
-+ char *file;
-+ int err;
-+
-+ file = inode_dentry_name(ino, dentry);
-+ if(file == NULL) return(-ENOMEM);
-+ err = do_rmdir(file);
-+ kfree(file);
-+ return(err);
-+}
-+
-+int hostfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev)
-+{
-+ struct inode *inode;
-+ char *name;
-+ int error;
-+
-+ inode = get_inode(dir->i_sb, dentry, &error);
-+ if(error) return(error);
-+ name = dentry_name(dentry, 0);
-+ if(name == NULL){
-+ iput(inode);
-+ return(-ENOMEM);
-+ }
-+ init_special_inode(inode, mode, dev);
-+ error = do_mknod(name, mode, dev);
-+ if(!error) error = read_name(inode, name);
-+ kfree(name);
-+ if(error){
-+ iput(inode);
-+ return(error);
-+ }
-+ d_instantiate(dentry, inode);
-+ return(0);
-+}
-+
-+int hostfs_rename(struct inode *from_ino, struct dentry *from,
-+ struct inode *to_ino, struct dentry *to)
-+{
-+ char *from_name, *to_name;
-+ int err;
-+
-+ from_name = inode_dentry_name(from_ino, from);
-+ if(from_name == NULL)
-+ return(-ENOMEM);
-+ to_name = inode_dentry_name(to_ino, to);
-+ if(to_name == NULL){
-+ kfree(from_name);
-+ return(-ENOMEM);
-+ }
-+ err = rename_file(from_name, to_name);
-+ kfree(from_name);
-+ kfree(to_name);
-+ return(err);
-+}
-+
-+void hostfs_truncate(struct inode *ino)
-+{
-+ not_implemented();
-+}
-+
-+int hostfs_permission(struct inode *ino, int desired)
-+{
-+ char *name;
-+ int r = 0, w = 0, x = 0, err;
-+
-+ if(desired & MAY_READ) r = 1;
-+ if(desired & MAY_WRITE) w = 1;
-+ if(desired & MAY_EXEC) x = 1;
-+ name = inode_name(ino, 0);
-+ if(name == NULL) return(-ENOMEM);
-+ err = access_file(name, r, w, x);
-+ kfree(name);
-+ if(!err) err = vfs_permission(ino, desired);
-+ return(err);
-+}
-+
-+int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
-+{
-+ struct hostfs_iattr attrs;
-+ char *name;
-+ int err;
-+
-+ if(append)
-+ attr->ia_valid &= ~ATTR_SIZE;
-+
-+ attrs.ia_valid = 0;
-+ if(attr->ia_valid & ATTR_MODE){
-+ attrs.ia_valid |= HOSTFS_ATTR_MODE;
-+ attrs.ia_mode = attr->ia_mode;
-+ }
-+ if(attr->ia_valid & ATTR_UID){
-+ if(kdev_same(dentry->d_inode->i_sb->s_dev, ROOT_DEV) &&
-+ (attr->ia_uid == 0))
-+ attr->ia_uid = getuid();
-+ attrs.ia_valid |= HOSTFS_ATTR_UID;
-+ attrs.ia_uid = attr->ia_uid;
-+ }
-+ if(attr->ia_valid & ATTR_GID){
-+ if(kdev_same(dentry->d_inode->i_sb->s_dev, ROOT_DEV) &&
-+ (attr->ia_gid == 0))
-+ attr->ia_gid = getuid();
-+ attrs.ia_valid |= HOSTFS_ATTR_GID;
-+ attrs.ia_gid = attr->ia_gid;
-+ }
-+ if(attr->ia_valid & ATTR_SIZE){
-+ attrs.ia_valid |= HOSTFS_ATTR_SIZE;
-+ attrs.ia_size = attr->ia_size;
-+ }
-+ if(attr->ia_valid & ATTR_ATIME){
-+ attrs.ia_valid |= HOSTFS_ATTR_ATIME;
-+ attrs.ia_atime = attr->ia_atime;
-+ }
-+ if(attr->ia_valid & ATTR_MTIME){
-+ attrs.ia_valid |= HOSTFS_ATTR_MTIME;
-+ attrs.ia_mtime = attr->ia_mtime;
-+ }
-+ if(attr->ia_valid & ATTR_CTIME){
-+ attrs.ia_valid |= HOSTFS_ATTR_CTIME;
-+ attrs.ia_ctime = attr->ia_ctime;
-+ }
-+ if(attr->ia_valid & ATTR_ATIME_SET){
-+ attrs.ia_valid |= HOSTFS_ATTR_ATIME_SET;
-+ }
-+ if(attr->ia_valid & ATTR_MTIME_SET){
-+ attrs.ia_valid |= HOSTFS_ATTR_MTIME_SET;
-+ }
-+ name = dentry_name(dentry, 0);
-+ if(name == NULL) return(-ENOMEM);
-+ err = set_attr(name, &attrs);
-+ kfree(name);
-+ if(err)
-+ return(err);
-+
-+ return(inode_setattr(dentry->d_inode, attr));
-+}
-+
-+int hostfs_getattr(struct dentry *dentry, struct iattr *attr)
-+{
-+ not_implemented();
-+ return(-EINVAL);
-+}
-+
-+static struct inode_operations hostfs_iops = {
-+ .create = hostfs_create,
-+ .link = hostfs_link,
-+ .unlink = hostfs_unlink,
-+ .symlink = hostfs_symlink,
-+ .mkdir = hostfs_mkdir,
-+ .rmdir = hostfs_rmdir,
-+ .mknod = hostfs_mknod,
-+ .rename = hostfs_rename,
-+ .truncate = hostfs_truncate,
-+ .permission = hostfs_permission,
-+ .setattr = hostfs_setattr,
-+ .getattr = hostfs_getattr,
-+};
-+
-+static struct inode_operations hostfs_dir_iops = {
-+ .create = hostfs_create,
-+ .lookup = hostfs_lookup,
-+ .link = hostfs_link,
-+ .unlink = hostfs_unlink,
-+ .symlink = hostfs_symlink,
-+ .mkdir = hostfs_mkdir,
-+ .rmdir = hostfs_rmdir,
-+ .mknod = hostfs_mknod,
-+ .rename = hostfs_rename,
-+ .truncate = hostfs_truncate,
-+ .permission = hostfs_permission,
-+ .setattr = hostfs_setattr,
-+ .getattr = hostfs_getattr,
-+};
-+
-+int hostfs_link_readpage(struct file *file, struct page *page)
-+{
-+ char *buffer, *name;
-+ long long start;
-+ int err;
-+
-+ start = page->index << PAGE_CACHE_SHIFT;
-+ buffer = kmap(page);
-+ name = inode_name(page->mapping->host, 0);
-+ if(name == NULL) return(-ENOMEM);
-+ err = do_readlink(name, buffer, PAGE_CACHE_SIZE);
-+ kfree(name);
-+ if(err == PAGE_CACHE_SIZE)
-+ err = -E2BIG;
-+ else if(err > 0){
-+ flush_dcache_page(page);
-+ SetPageUptodate(page);
-+ if (PageError(page)) ClearPageError(page);
-+ err = 0;
-+ }
-+ kunmap(page);
-+ UnlockPage(page);
-+ return(err);
-+}
-+
-+static struct address_space_operations hostfs_link_aops = {
-+ .readpage = hostfs_link_readpage,
-+};
-+
-+static char *get_root(char *mount_arg)
-+{
-+ char *root, *slash = "";
-+ int len = 0;
-+
-+ if(jail_dir != NULL){
-+ len += strlen(jail_dir);
-+ if((*jail_dir == '\0') ||
-+ (jail_dir[strlen(jail_dir) - 1] != '/'))
-+ slash = "/";
-+ len += strlen(slash);
-+ }
-+
-+ if((mount_arg == NULL) || (*mount_arg == '\0'))
-+ mount_arg = DEFAULT_ROOT;
-+
-+ len += strlen(mount_arg) + 1;
-+
-+ root = kmalloc(len, GFP_KERNEL);
-+ if(root == NULL)
-+ return(NULL);
-+
-+ if(jail_dir != NULL)
-+ sprintf(root, "%s%s%s", jail_dir, slash, mount_arg);
-+ else
-+ strcpy(root, mount_arg);
-+
-+ return(root);
-+}
-+
-+struct super_block *hostfs_read_super(struct super_block *sb, void *data,
-+ int silent)
-+{
-+ struct inode *root_inode;
-+ char *root_dir;
-+
-+ sb->s_blocksize = 1024;
-+ sb->s_blocksize_bits = 10;
-+ sb->s_magic = HOSTFS_SUPER_MAGIC;
-+ sb->s_op = &hostfs_sbops;
-+
-+ root_inode = get_inode(sb, NULL, NULL);
-+ if(root_inode == NULL)
-+ goto out;
-+
-+ root_dir = get_root(data);
-+ if(root_dir == NULL)
-+ goto out_put;
-+
-+ root_inode->u.hostfs_i.host_filename = root_dir;
-+ sb->s_root = d_alloc_root(root_inode);
-+ if(sb->s_root == NULL)
-+ goto out_free;
-+
-+ if(read_inode(root_inode))
-+ goto out_dput;
-+ return(sb);
-+
-+ out_dput:
-+ dput(sb->s_root);
-+ out_free:
-+ kfree(root_dir);
-+ out_put:
-+ make_bad_inode(root_inode);
-+ iput(root_inode);
-+ out:
-+ return(NULL);
-+}
-+
-+DECLARE_FSTYPE(hostfs_type, "hostfs", hostfs_read_super, 0);
-+
-+static int __init init_hostfs(void)
-+{
-+ return(register_filesystem(&hostfs_type));
-+}
-+
-+static void __exit exit_hostfs(void)
-+{
-+ unregister_filesystem(&hostfs_type);
-+}
-+
-+module_init(init_hostfs)
-+module_exit(exit_hostfs)
-+MODULE_LICENSE("GPL");
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/fs/hostfs/hostfs_user.c um/arch/um/fs/hostfs/hostfs_user.c
---- orig/arch/um/fs/hostfs/hostfs_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/fs/hostfs/hostfs_user.c 2003-11-14 08:51:20.000000000 -0500
-@@ -0,0 +1,359 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <unistd.h>
-+#include <stdio.h>
-+#include <fcntl.h>
-+#include <dirent.h>
-+#include <errno.h>
-+#include <utime.h>
-+#include <string.h>
-+#include <sys/stat.h>
-+#include <sys/time.h>
-+#include <sys/vfs.h>
-+#include "hostfs.h"
-+#include "kern_util.h"
-+#include "user.h"
-+
-+int stat_file(const char *path, int *dev_out, unsigned long long *inode_out,
-+ int *mode_out, int *nlink_out, int *uid_out, int *gid_out,
-+ unsigned long long *size_out, unsigned long *atime_out,
-+ unsigned long *mtime_out, unsigned long *ctime_out,
-+ int *blksize_out, unsigned long long *blocks_out)
-+{
-+ struct stat64 buf;
-+
-+ if(lstat64(path, &buf) < 0)
-+ return(-errno);
-+ if(dev_out != NULL) *dev_out = buf.st_dev;
-+
-+ /* See the Makefile for why STAT64_INO_FIELD is passed in
-+ * by the build
-+ */
-+ if(inode_out != NULL) *inode_out = buf.STAT64_INO_FIELD;
-+ if(mode_out != NULL) *mode_out = buf.st_mode;
-+ if(nlink_out != NULL) *nlink_out = buf.st_nlink;
-+ if(uid_out != NULL) *uid_out = buf.st_uid;
-+ if(gid_out != NULL) *gid_out = buf.st_gid;
-+ if(size_out != NULL) *size_out = buf.st_size;
-+ if(atime_out != NULL) *atime_out = buf.st_atime;
-+ if(mtime_out != NULL) *mtime_out = buf.st_mtime;
-+ if(ctime_out != NULL) *ctime_out = buf.st_ctime;
-+ if(blksize_out != NULL) *blksize_out = buf.st_blksize;
-+ if(blocks_out != NULL) *blocks_out = buf.st_blocks;
-+ return(0);
-+}
-+
-+int file_type(const char *path, int *rdev)
-+{
-+ struct stat64 buf;
-+
-+ if(lstat64(path, &buf) < 0)
-+ return(-errno);
-+ if(rdev != NULL)
-+ *rdev = buf.st_rdev;
-+
-+ if(S_ISDIR(buf.st_mode)) return(OS_TYPE_DIR);
-+ else if(S_ISLNK(buf.st_mode)) return(OS_TYPE_SYMLINK);
-+ else if(S_ISCHR(buf.st_mode)) return(OS_TYPE_CHARDEV);
-+ else if(S_ISBLK(buf.st_mode)) return(OS_TYPE_BLOCKDEV);
-+ else if(S_ISFIFO(buf.st_mode))return(OS_TYPE_FIFO);
-+ else if(S_ISSOCK(buf.st_mode))return(OS_TYPE_SOCK);
-+ else return(OS_TYPE_FILE);
-+}
-+
-+int access_file(char *path, int r, int w, int x)
-+{
-+ int mode = 0;
-+
-+ if(r) mode = R_OK;
-+ if(w) mode |= W_OK;
-+ if(x) mode |= X_OK;
-+ if(access(path, mode) != 0) return(-errno);
-+ else return(0);
-+}
-+
-+int open_file(char *path, int r, int w, int append)
-+{
-+ int mode = 0, fd;
-+
-+ if(r && !w)
-+ mode = O_RDONLY;
-+ else if(!r && w)
-+ mode = O_WRONLY;
-+ else if(r && w)
-+ mode = O_RDWR;
-+ else panic("Impossible mode in open_file");
-+
-+ if(append)
-+ mode |= O_APPEND;
-+ fd = open64(path, mode);
-+ if(fd < 0) return(-errno);
-+ else return(fd);
-+}
-+
-+void *open_dir(char *path, int *err_out)
-+{
-+ DIR *dir;
-+
-+ dir = opendir(path);
-+ *err_out = errno;
-+ if(dir == NULL) return(NULL);
-+ return(dir);
-+}
-+
-+char *read_dir(void *stream, unsigned long long *pos,
-+ unsigned long long *ino_out, int *len_out)
-+{
-+ DIR *dir = stream;
-+ struct dirent *ent;
-+
-+ seekdir(dir, *pos);
-+ ent = readdir(dir);
-+ if(ent == NULL) return(NULL);
-+ *len_out = strlen(ent->d_name);
-+ *ino_out = ent->d_ino;
-+ *pos = telldir(dir);
-+ return(ent->d_name);
-+}
-+
-+int read_file(int fd, unsigned long long *offset, char *buf, int len)
-+{
-+ int n, err;
-+
-+ err = os_seek_file(fd, *offset);
-+ if(err)
-+ return(err);
-+
-+ n = os_read_file(fd, buf, len);
-+ if(n < 0)
-+ return(n);
-+
-+ *offset += n;
-+ return(n);
-+}
-+
-+int write_file(int fd, unsigned long long *offset, const char *buf, int len)
-+{
-+ int n, err;
-+
-+ err = os_seek_file(fd, *offset);
-+ if(err)
-+ return(err);
-+
-+ n = os_write_file(fd, buf, len);
-+ if(n < 0)
-+ return(n);
-+
-+ *offset += n;
-+ return(n);
-+}
-+
-+int lseek_file(int fd, long long offset, int whence)
-+{
-+ int ret;
-+
-+ ret = lseek64(fd, offset, whence);
-+ if(ret < 0) return(-errno);
-+ return(0);
-+}
-+
-+void close_file(void *stream)
-+{
-+ close(*((int *) stream));
-+}
-+
-+void close_dir(void *stream)
-+{
-+ closedir(stream);
-+}
-+
-+int file_create(char *name, int ur, int uw, int ux, int gr,
-+ int gw, int gx, int or, int ow, int ox)
-+{
-+ int mode, fd;
-+
-+ mode = 0;
-+ mode |= ur ? S_IRUSR : 0;
-+ mode |= uw ? S_IWUSR : 0;
-+ mode |= ux ? S_IXUSR : 0;
-+ mode |= gr ? S_IRGRP : 0;
-+ mode |= gw ? S_IWGRP : 0;
-+ mode |= gx ? S_IXGRP : 0;
-+ mode |= or ? S_IROTH : 0;
-+ mode |= ow ? S_IWOTH : 0;
-+ mode |= ox ? S_IXOTH : 0;
-+ fd = open64(name, O_CREAT | O_RDWR, mode);
-+ if(fd < 0)
-+ return(-errno);
-+ return(fd);
-+}
-+
-+int set_attr(const char *file, struct hostfs_iattr *attrs)
-+{
-+ struct utimbuf buf;
-+ int err, ma;
-+
-+ if(attrs->ia_valid & HOSTFS_ATTR_MODE){
-+ if(chmod(file, attrs->ia_mode) != 0) return(-errno);
-+ }
-+ if(attrs->ia_valid & HOSTFS_ATTR_UID){
-+ if(chown(file, attrs->ia_uid, -1)) return(-errno);
-+ }
-+ if(attrs->ia_valid & HOSTFS_ATTR_GID){
-+ if(chown(file, -1, attrs->ia_gid)) return(-errno);
-+ }
-+ if(attrs->ia_valid & HOSTFS_ATTR_SIZE){
-+ if(truncate(file, attrs->ia_size)) return(-errno);
-+ }
-+ ma = HOSTFS_ATTR_ATIME_SET | HOSTFS_ATTR_MTIME_SET;
-+ if((attrs->ia_valid & ma) == ma){
-+ buf.actime = attrs->ia_atime;
-+ buf.modtime = attrs->ia_mtime;
-+ if(utime(file, &buf) != 0) return(-errno);
-+ }
-+ else {
-+ if(attrs->ia_valid & HOSTFS_ATTR_ATIME_SET){
-+ err = stat_file(file, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, NULL, &buf.modtime, NULL,
-+ NULL, NULL);
-+ if(err != 0) return(err);
-+ buf.actime = attrs->ia_atime;
-+ if(utime(file, &buf) != 0) return(-errno);
-+ }
-+ if(attrs->ia_valid & HOSTFS_ATTR_MTIME_SET){
-+ err = stat_file(file, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, &buf.actime, NULL, NULL,
-+ NULL, NULL);
-+ if(err != 0) return(err);
-+ buf.modtime = attrs->ia_mtime;
-+ if(utime(file, &buf) != 0) return(-errno);
-+ }
-+ }
-+ if(attrs->ia_valid & HOSTFS_ATTR_CTIME) ;
-+ if(attrs->ia_valid & (HOSTFS_ATTR_ATIME | HOSTFS_ATTR_MTIME)){
-+ err = stat_file(file, NULL, NULL, NULL, NULL, NULL,
-+ NULL, NULL, &attrs->ia_atime, &attrs->ia_mtime,
-+ NULL, NULL, NULL);
-+ if(err != 0) return(err);
-+ }
-+ return(0);
-+}
-+
-+int make_symlink(const char *from, const char *to)
-+{
-+ int err;
-+
-+ err = symlink(to, from);
-+ if(err) return(-errno);
-+ return(0);
-+}
-+
-+int unlink_file(const char *file)
-+{
-+ int err;
-+
-+ err = unlink(file);
-+ if(err) return(-errno);
-+ return(0);
-+}
-+
-+int do_mkdir(const char *file, int mode)
-+{
-+ int err;
-+
-+ err = mkdir(file, mode);
-+ if(err) return(-errno);
-+ return(0);
-+}
-+
-+int do_rmdir(const char *file)
-+{
-+ int err;
-+
-+ err = rmdir(file);
-+ if(err) return(-errno);
-+ return(0);
-+}
-+
-+int do_mknod(const char *file, int mode, int dev)
-+{
-+ int err;
-+
-+ err = mknod(file, mode, dev);
-+ if(err) return(-errno);
-+ return(0);
-+}
-+
-+int link_file(const char *to, const char *from)
-+{
-+ int err;
-+
-+ err = link(to, from);
-+ if(err) return(-errno);
-+ return(0);
-+}
-+
-+int do_readlink(char *file, char *buf, int size)
-+{
-+ int n;
-+
-+ n = readlink(file, buf, size);
-+ if(n < 0)
-+ return(-errno);
-+ if(n < size)
-+ buf[n] = '\0';
-+ return(n);
-+}
-+
-+int rename_file(char *from, char *to)
-+{
-+ int err;
-+
-+ err = rename(from, to);
-+ if(err < 0) return(-errno);
-+ return(0);
-+}
-+
-+int do_statfs(char *root, long *bsize_out, long long *blocks_out,
-+ long long *bfree_out, long long *bavail_out,
-+ long long *files_out, long long *ffree_out,
-+ void *fsid_out, int fsid_size, long *namelen_out,
-+ long *spare_out)
-+{
-+ struct statfs64 buf;
-+ int err;
-+
-+ err = statfs64(root, &buf);
-+ if(err < 0) return(-errno);
-+ *bsize_out = buf.f_bsize;
-+ *blocks_out = buf.f_blocks;
-+ *bfree_out = buf.f_bfree;
-+ *bavail_out = buf.f_bavail;
-+ *files_out = buf.f_files;
-+ *ffree_out = buf.f_ffree;
-+ memcpy(fsid_out, &buf.f_fsid,
-+ sizeof(buf.f_fsid) > fsid_size ? fsid_size :
-+ sizeof(buf.f_fsid));
-+ *namelen_out = buf.f_namelen;
-+ spare_out[0] = buf.f_spare[0];
-+ spare_out[1] = buf.f_spare[1];
-+ spare_out[2] = buf.f_spare[2];
-+ spare_out[3] = buf.f_spare[3];
-+ spare_out[4] = buf.f_spare[4];
-+ spare_out[5] = buf.f_spare[5];
-+ return(0);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/fs/hostfs/Makefile um/arch/um/fs/hostfs/Makefile
---- orig/arch/um/fs/hostfs/Makefile 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/fs/hostfs/Makefile 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,24 @@
-+#
-+# Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+# Licensed under the GPL
-+#
-+
-+# struct stat64 changed the inode field name between 2.2 and 2.4 from st_ino
-+# to __st_ino. It stayed in the same place, so as long as the correct name
-+# is used, hostfs compiled on 2.2 should work on 2.4 and vice versa.
-+
-+STAT64_INO_FIELD := $(shell grep -q __st_ino /usr/include/bits/stat.h && \
-+ echo __)st_ino
-+
-+USER_CFLAGS := $(USER_CFLAGS) -DSTAT64_INO_FIELD=$(STAT64_INO_FIELD)
-+
-+O_TARGET := hostfs.o
-+obj-y = hostfs_kern.o hostfs_user.o
-+obj-m = $(O_TARGET)
-+
-+USER_OBJS = $(filter %_user.o,$(obj-y))
-+
-+include $(TOPDIR)/Rules.make
-+
-+$(USER_OBJS) : %.o: %.c
-+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $<
-diff -Naur -X ../exclude-files orig/arch/um/fs/hppfs/hppfs_kern.c um/arch/um/fs/hppfs/hppfs_kern.c
---- orig/arch/um/fs/hppfs/hppfs_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/fs/hppfs/hppfs_kern.c 2004-01-08 23:35:58.000000000 -0500
-@@ -0,0 +1,737 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include <linux/list.h>
-+#include <linux/kernel.h>
-+#include <linux/ctype.h>
-+#include <asm/uaccess.h>
-+#include "os.h"
-+
-+struct hppfs_data {
-+ struct list_head list;
-+ char contents[PAGE_SIZE - sizeof(struct list_head)];
-+};
-+
-+struct hppfs_private {
-+ struct file proc_file;
-+ int host_fd;
-+ loff_t len;
-+ struct hppfs_data *contents;
-+};
-+
-+#define HPPFS_SUPER_MAGIC 0xb00000ee
-+
-+static struct super_operations hppfs_sbops;
-+
-+static struct inode *get_inode(struct super_block *sb, struct dentry *dentry,
-+ int *error);
-+
-+static int is_pid(struct dentry *dentry)
-+{
-+ struct super_block *sb;
-+ int i;
-+
-+ sb = dentry->d_sb;
-+ if((sb->s_op != &hppfs_sbops) || (dentry->d_parent != sb->s_root))
-+ return(0);
-+
-+ for(i = 0; i < dentry->d_name.len; i++){
-+ if(!isdigit(dentry->d_name.name[i]))
-+ return(0);
-+ }
-+ return(1);
-+}
-+
-+static char *dentry_name(struct dentry *dentry, int extra)
-+{
-+ struct dentry *parent;
-+ char *root, *name;
-+ const char *seg_name;
-+ int len, seg_len;
-+
-+ len = 0;
-+ parent = dentry;
-+ while(parent->d_parent != parent){
-+ if(is_pid(parent))
-+ len += strlen("pid") + 1;
-+ else len += parent->d_name.len + 1;
-+ parent = parent->d_parent;
-+ }
-+
-+ root = "proc";
-+ len += strlen(root);
-+ name = kmalloc(len + extra + 1, GFP_KERNEL);
-+ if(name == NULL) return(NULL);
-+
-+ name[len] = '\0';
-+ parent = dentry;
-+ while(parent->d_parent != parent){
-+ if(is_pid(parent)){
-+ seg_name = "pid";
-+ seg_len = strlen("pid");
-+ }
-+ else {
-+ seg_name = parent->d_name.name;
-+ seg_len = parent->d_name.len;
-+ }
-+
-+ len -= seg_len + 1;
-+ name[len] = '/';
-+ strncpy(&name[len + 1], seg_name, seg_len);
-+ parent = parent->d_parent;
-+ }
-+ strncpy(name, root, strlen(root));
-+ return(name);
-+}
-+
-+struct dentry_operations hppfs_dentry_ops = {
-+};
-+
-+static int file_removed(struct dentry *dentry, const char *file)
-+{
-+ char *host_file;
-+ int extra, fd;
-+
-+ extra = 0;
-+ if(file != NULL) extra += strlen(file) + 1;
-+
-+ host_file = dentry_name(dentry, extra + strlen("/remove"));
-+ if(host_file == NULL){
-+ printk("file_removed : allocation failed\n");
-+ return(-ENOMEM);
-+ }
-+
-+ if(file != NULL){
-+ strcat(host_file, "/");
-+ strcat(host_file, file);
-+ }
-+ strcat(host_file, "/remove");
-+
-+ fd = os_open_file(host_file, of_read(OPENFLAGS()), 0);
-+ kfree(host_file);
-+ if(fd >= 0){
-+ os_close_file(fd);
-+ return(1);
-+ }
-+ return(0);
-+}
-+
-+static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry)
-+{
-+ struct dentry *proc_dentry;
-+ struct inode *inode;
-+ int err, deleted;
-+
-+ deleted = file_removed(dentry, NULL);
-+ if(deleted < 0)
-+ return(ERR_PTR(deleted));
-+ else if(deleted)
-+ return(ERR_PTR(-ENOENT));
-+
-+ proc_dentry = lookup_hash(&dentry->d_name, ino->u.hppfs_i.proc_dentry);
-+ if(IS_ERR(proc_dentry))
-+ return(proc_dentry);
-+
-+ inode = get_inode(ino->i_sb, proc_dentry, &err);
-+ if(err != 0)
-+ return(ERR_PTR(err));
-+
-+ d_add(dentry, inode);
-+ dentry->d_op = &hppfs_dentry_ops;
-+ return(NULL);
-+}
-+
-+static struct inode_operations hppfs_file_iops = {
-+};
-+
-+static struct inode_operations hppfs_dir_iops = {
-+ .lookup = hppfs_lookup,
-+};
-+
-+static ssize_t read_proc(struct file *file, char *buf, ssize_t count,
-+ loff_t *ppos, int is_user)
-+{
-+ ssize_t (*read)(struct file *, char *, size_t, loff_t *);
-+ ssize_t n;
-+
-+ read = file->f_dentry->d_inode->i_fop->read;
-+ if(read == NULL)
-+ return(-EOPNOTSUPP);
-+
-+ if(!is_user)
-+ set_fs(KERNEL_DS);
-+
-+ n = (*read)(file, buf, count, &file->f_pos);
-+
-+ if(!is_user)
-+ set_fs(USER_DS);
-+
-+ if(ppos) *ppos = file->f_pos;
-+ return(n);
-+}
-+
-+static ssize_t hppfs_read_file(int fd, char *buf, ssize_t count)
-+{
-+ ssize_t n;
-+ int cur, err;
-+ char *new_buf;
-+
-+ n = -ENOMEM;
-+ new_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
-+ if(new_buf == NULL){
-+ printk("hppfs_read_file : kmalloc failed\n");
-+ goto out;
-+ }
-+ n = 0;
-+ while(count > 0){
-+ cur = min_t(ssize_t, count, PAGE_SIZE);
-+ err = os_read_file(fd, new_buf, cur);
-+ if(err < 0){
-+ printk("hppfs_read : read failed, err = %d\n", -err);
-+ n = err;
-+ goto out_free;
-+ }
-+ else if(err == 0)
-+ break;
-+
-+ if(copy_to_user(buf, new_buf, err)){
-+ n = -EFAULT;
-+ goto out_free;
-+ }
-+ n += err;
-+ count -= err;
-+ }
-+ out_free:
-+ kfree(new_buf);
-+ out:
-+ return(n);
-+}
-+
-+static ssize_t hppfs_read(struct file *file, char *buf, size_t count,
-+ loff_t *ppos)
-+{
-+ struct hppfs_private *hppfs = file->private_data;
-+ struct hppfs_data *data;
-+ loff_t off;
-+ int err;
-+
-+ if(hppfs->contents != NULL){
-+ if(*ppos >= hppfs->len) return(0);
-+
-+ data = hppfs->contents;
-+ off = *ppos;
-+ while(off >= sizeof(data->contents)){
-+ data = list_entry(data->list.next, struct hppfs_data,
-+ list);
-+ off -= sizeof(data->contents);
-+ }
-+
-+ if(off + count > hppfs->len)
-+ count = hppfs->len - off;
-+ copy_to_user(buf, &data->contents[off], count);
-+ *ppos += count;
-+ }
-+ else if(hppfs->host_fd != -1){
-+ err = os_seek_file(hppfs->host_fd, *ppos);
-+ if(err < 0){
-+ printk("hppfs_read : seek failed, err = %d\n", -err);
-+ return(err);
-+ }
-+ count = hppfs_read_file(hppfs->host_fd, buf, count);
-+ if(count > 0)
-+ *ppos += count;
-+ }
-+ else count = read_proc(&hppfs->proc_file, buf, count, ppos, 1);
-+
-+ return(count);
-+}
-+
-+static ssize_t hppfs_write(struct file *file, const char *buf, size_t len,
-+ loff_t *ppos)
-+{
-+ struct hppfs_private *data = file->private_data;
-+ struct file *proc_file = &data->proc_file;
-+ ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
-+ int err;
-+
-+ write = proc_file->f_dentry->d_inode->i_fop->write;
-+ if(write == NULL)
-+ return(-EOPNOTSUPP);
-+
-+ proc_file->f_pos = file->f_pos;
-+ err = (*write)(proc_file, buf, len, &proc_file->f_pos);
-+ file->f_pos = proc_file->f_pos;
-+
-+ return(err);
-+}
-+
-+static int open_host_sock(char *host_file, int *filter_out)
-+{
-+ char *end;
-+ int fd;
-+
-+ end = &host_file[strlen(host_file)];
-+ strcpy(end, "/rw");
-+ *filter_out = 1;
-+ fd = os_connect_socket(host_file);
-+ if(fd >= 0)
-+ return(fd);
-+
-+ strcpy(end, "/r");
-+ *filter_out = 0;
-+ fd = os_connect_socket(host_file);
-+ return(fd);
-+}
-+
-+static void free_contents(struct hppfs_data *head)
-+{
-+ struct hppfs_data *data;
-+ struct list_head *ele, *next;
-+
-+ if(head == NULL) return;
-+
-+ list_for_each_safe(ele, next, &head->list){
-+ data = list_entry(ele, struct hppfs_data, list);
-+ kfree(data);
-+ }
-+ kfree(head);
-+}
-+
-+static struct hppfs_data *hppfs_get_data(int fd, int filter,
-+ struct file *proc_file,
-+ struct file *hppfs_file,
-+ loff_t *size_out)
-+{
-+ struct hppfs_data *data, *new, *head;
-+ int n, err;
-+
-+ err = -ENOMEM;
-+ data = kmalloc(sizeof(*data), GFP_KERNEL);
-+ if(data == NULL){
-+ printk("hppfs_get_data : head allocation failed\n");
-+ goto failed;
-+ }
-+
-+ INIT_LIST_HEAD(&data->list);
-+
-+ head = data;
-+ *size_out = 0;
-+
-+ if(filter){
-+ while((n = read_proc(proc_file, data->contents,
-+ sizeof(data->contents), NULL, 0)) > 0) {
-+ err = os_write_file(fd, data->contents, n);
-+ if(err != n)
-+ printk("hppfs_get_data : failed to write out "
-+ "%d bytes, err = %d\n", n, -err);
-+ }
-+ err = os_shutdown_socket(fd, 0, 1);
-+ if(err < 0){
-+ printk("hppfs_get_data : failed to shut down "
-+ "socket\n");
-+ goto failed_free;
-+ }
-+ }
-+ while(1){
-+ n = os_read_file(fd, data->contents, sizeof(data->contents));
-+ if(n < 0){
-+ err = n;
-+ printk("hppfs_get_data : read failed, err = %d\n", -n);
-+ goto failed_free;
-+ }
-+ else if(n == 0)
-+ break;
-+
-+ *size_out += n;
-+
-+ if(n < sizeof(data->contents))
-+ break;
-+
-+ new = kmalloc(sizeof(*data), GFP_KERNEL);
-+ if(new == 0){
-+ printk("hppfs_get_data : data allocation failed\n");
-+ err = -ENOMEM;
-+ goto failed_free;
-+ }
-+
-+ INIT_LIST_HEAD(&new->list);
-+ list_add(&new->list, &data->list);
-+ data = new;
-+ }
-+ return(head);
-+
-+ failed_free:
-+ free_contents(head);
-+ failed:
-+ return(ERR_PTR(err));
-+}
-+
-+static struct hppfs_private *hppfs_data(void)
-+{
-+ struct hppfs_private *data;
-+
-+ data = kmalloc(sizeof(*data), GFP_KERNEL);
-+ if(data == NULL)
-+ return(data);
-+
-+ *data = ((struct hppfs_private ) { .host_fd = -1,
-+ .len = -1,
-+ .contents = NULL } );
-+ return(data);
-+}
-+
-+static int hppfs_open(struct inode *inode, struct file *file)
-+{
-+ struct hppfs_private *data;
-+ struct dentry *proc_dentry;
-+ char *host_file;
-+ int err, fd, type, filter;
-+
-+ err = -ENOMEM;
-+ data = hppfs_data();
-+ if(data == NULL)
-+ goto out;
-+
-+ host_file = dentry_name(file->f_dentry, strlen("/rw"));
-+ if(host_file == NULL)
-+ goto out_free2;
-+
-+ proc_dentry = inode->u.hppfs_i.proc_dentry;
-+ err = init_private_file(&data->proc_file, proc_dentry, file->f_mode);
-+ if(err)
-+ goto out_free1;
-+
-+ type = os_file_type(host_file);
-+ if(type == OS_TYPE_FILE){
-+ fd = os_open_file(host_file, of_read(OPENFLAGS()), 0);
-+ if(fd >= 0)
-+ data->host_fd = fd;
-+ else printk("hppfs_open : failed to open '%s', err = %d\n",
-+ host_file, -fd);
-+
-+ data->contents = NULL;
-+ }
-+ else if(type == OS_TYPE_DIR){
-+ fd = open_host_sock(host_file, &filter);
-+ if(fd >= 0){
-+ data->contents = hppfs_get_data(fd, filter,
-+ &data->proc_file,
-+ file, &data->len);
-+ if(!IS_ERR(data->contents))
-+ data->host_fd = fd;
-+ }
-+ else printk("hppfs_open : failed to open a socket in "
-+ "'%s', err = %d\n", host_file, -fd);
-+ }
-+ kfree(host_file);
-+
-+ file->private_data = data;
-+ return(0);
-+
-+ out_free1:
-+ kfree(host_file);
-+ out_free2:
-+ free_contents(data->contents);
-+ kfree(data);
-+ out:
-+ return(err);
-+}
-+
-+static int hppfs_dir_open(struct inode *inode, struct file *file)
-+{
-+ struct hppfs_private *data;
-+ struct dentry *proc_dentry;
-+ int err;
-+
-+ err = -ENOMEM;
-+ data = hppfs_data();
-+ if(data == NULL)
-+ goto out;
-+
-+ proc_dentry = inode->u.hppfs_i.proc_dentry;
-+ err = init_private_file(&data->proc_file, proc_dentry, file->f_mode);
-+ if(err)
-+ goto out_free;
-+
-+ file->private_data = data;
-+ return(0);
-+
-+ out_free:
-+ kfree(data);
-+ out:
-+ return(err);
-+}
-+
-+static loff_t hppfs_llseek(struct file *file, loff_t off, int where)
-+{
-+ struct hppfs_private *data = file->private_data;
-+ struct file *proc_file = &data->proc_file;
-+ loff_t (*llseek)(struct file *, loff_t, int);
-+ loff_t ret;
-+
-+ llseek = proc_file->f_dentry->d_inode->i_fop->llseek;
-+ if(llseek != NULL){
-+ ret = (*llseek)(proc_file, off, where);
-+ if(ret < 0)
-+ return(ret);
-+ }
-+
-+ return(default_llseek(file, off, where));
-+}
-+
-+struct hppfs_dirent {
-+ void *vfs_dirent;
-+ filldir_t filldir;
-+ struct dentry *dentry;
-+};
-+
-+static int hppfs_filldir(void *d, const char *name, int size,
-+ loff_t offset, ino_t inode, unsigned int type)
-+{
-+ struct hppfs_dirent *dirent = d;
-+
-+ if(file_removed(dirent->dentry, name))
-+ return(0);
-+
-+ return((*dirent->filldir)(dirent->vfs_dirent, name, size, offset,
-+ inode, type));
-+}
-+
-+static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir)
-+{
-+ struct hppfs_private *data = file->private_data;
-+ struct file *proc_file = &data->proc_file;
-+ int (*readdir)(struct file *, void *, filldir_t);
-+ struct hppfs_dirent dirent = ((struct hppfs_dirent)
-+ { .vfs_dirent = ent,
-+ .filldir = filldir,
-+ .dentry = file->f_dentry } );
-+ int err;
-+
-+ readdir = proc_file->f_dentry->d_inode->i_fop->readdir;
-+ if(readdir == NULL)
-+ return(-EOPNOTSUPP);
-+
-+ proc_file->f_pos = file->f_pos;
-+ err = (*readdir)(proc_file, &dirent, hppfs_filldir);
-+ file->f_pos = proc_file->f_pos;
-+
-+ return(err);
-+}
-+
-+static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync)
-+{
-+ return(0);
-+}
-+
-+static struct file_operations hppfs_file_fops = {
-+ .owner = NULL,
-+ .llseek = hppfs_llseek,
-+ .read = hppfs_read,
-+ .write = hppfs_write,
-+ .open = hppfs_open,
-+};
-+
-+static struct file_operations hppfs_dir_fops = {
-+ .owner = NULL,
-+ .readdir = hppfs_readdir,
-+ .open = hppfs_dir_open,
-+ .fsync = hppfs_fsync,
-+};
-+
-+static int hppfs_statfs(struct super_block *sb, struct statfs *sf)
-+{
-+ sf->f_blocks = 0;
-+ sf->f_bfree = 0;
-+ sf->f_bavail = 0;
-+ sf->f_files = 0;
-+ sf->f_ffree = 0;
-+ sf->f_type = HPPFS_SUPER_MAGIC;
-+ return(0);
-+}
-+
-+static struct super_operations hppfs_sbops = {
-+ .put_inode = force_delete,
-+ .delete_inode = NULL,
-+ .statfs = hppfs_statfs,
-+};
-+
-+static int hppfs_readlink(struct dentry *dentry, char *buffer, int buflen)
-+{
-+ struct file proc_file;
-+ struct dentry *proc_dentry;
-+ int (*readlink)(struct dentry *, char *, int);
-+ int err, n;
-+
-+ proc_dentry = dentry->d_inode->u.hppfs_i.proc_dentry;
-+ err = init_private_file(&proc_file, proc_dentry, FMODE_READ);
-+ if(err)
-+ return(err);
-+
-+ readlink = proc_dentry->d_inode->i_op->readlink;
-+ if(readlink == NULL)
-+ return(-EOPNOTSUPP);
-+ n = (*readlink)(proc_dentry, buffer, buflen);
-+
-+ if(proc_file.f_op->release)
-+ (*proc_file.f_op->release)(proc_dentry->d_inode, &proc_file);
-+
-+ return(n);
-+}
-+
-+static int hppfs_follow_link(struct dentry *dentry, struct nameidata *nd)
-+{
-+ struct file proc_file;
-+ struct dentry *proc_dentry;
-+ int (*follow_link)(struct dentry *, struct nameidata *);
-+ int err, n;
-+
-+ proc_dentry = dentry->d_inode->u.hppfs_i.proc_dentry;
-+ err = init_private_file(&proc_file, proc_dentry, FMODE_READ);
-+ if(err)
-+ return(err);
-+
-+ follow_link = proc_dentry->d_inode->i_op->follow_link;
-+ if(follow_link == NULL)
-+ return(-EOPNOTSUPP);
-+ n = (*follow_link)(proc_dentry, nd);
-+
-+ if(proc_file.f_op->release)
-+ (*proc_file.f_op->release)(proc_dentry->d_inode, &proc_file);
-+
-+ return(n);
-+}
-+
-+static struct inode_operations hppfs_link_iops = {
-+ .readlink = hppfs_readlink,
-+ .follow_link = hppfs_follow_link,
-+};
-+
-+static void read_inode(struct inode *ino)
-+{
-+ struct inode *proc_ino;
-+
-+ proc_ino = ino->u.hppfs_i.proc_dentry->d_inode;
-+ ino->i_uid = proc_ino->i_uid;
-+ ino->i_gid = proc_ino->i_gid;
-+ ino->i_atime = proc_ino->i_atime;
-+ ino->i_mtime = proc_ino->i_mtime;
-+ ino->i_ctime = proc_ino->i_ctime;
-+ ino->i_ino = proc_ino->i_ino;
-+ ino->i_dev = proc_ino->i_dev;
-+ ino->i_mode = proc_ino->i_mode;
-+ ino->i_nlink = proc_ino->i_nlink;
-+ ino->i_size = proc_ino->i_size;
-+ ino->i_blksize = proc_ino->i_blksize;
-+ ino->i_blocks = proc_ino->i_blocks;
-+}
-+
-+static struct inode *get_inode(struct super_block *sb, struct dentry *dentry,
-+ int *error)
-+{
-+ struct inode *inode;
-+ int err = -ENOMEM;
-+
-+ inode = new_inode(sb);
-+ if(inode == NULL)
-+ goto out;
-+
-+ insert_inode_hash(inode);
-+ if(S_ISDIR(dentry->d_inode->i_mode)){
-+ inode->i_op = &hppfs_dir_iops;
-+ inode->i_fop = &hppfs_dir_fops;
-+ }
-+ else if(S_ISLNK(dentry->d_inode->i_mode)){
-+ inode->i_op = &hppfs_link_iops;
-+ inode->i_fop = &hppfs_file_fops;
-+ }
-+ else {
-+ inode->i_op = &hppfs_file_iops;
-+ inode->i_fop = &hppfs_file_fops;
-+ }
-+
-+ inode->i_sb = sb;
-+ inode->u.hppfs_i.proc_dentry = dentry;
-+
-+ read_inode(inode);
-+ err = 0;
-+
-+ if(error) *error = err;
-+ return(inode);
-+ out:
-+ if(error) *error = err;
-+ return(NULL);
-+}
-+
-+static struct super_block *hppfs_read_super(struct super_block *sb, void *d,
-+ int silent)
-+{
-+ struct inode *root_inode;
-+ struct file_system_type *procfs;
-+ struct super_block *proc_sb;
-+
-+ procfs = get_fs_type("proc");
-+ if(procfs == NULL)
-+ goto out;
-+
-+ if(list_empty(&procfs->fs_supers))
-+ goto out;
-+
-+ proc_sb = list_entry(procfs->fs_supers.next, struct super_block,
-+ s_instances);
-+
-+ sb->s_blocksize = 1024;
-+ sb->s_blocksize_bits = 10;
-+ sb->s_magic = HPPFS_SUPER_MAGIC;
-+ sb->s_op = &hppfs_sbops;
-+
-+ dget(proc_sb->s_root);
-+ root_inode = get_inode(sb, proc_sb->s_root, NULL);
-+ if(root_inode == NULL)
-+ goto out_dput;
-+
-+ sb->s_root = d_alloc_root(root_inode);
-+ if(sb->s_root == NULL)
-+ goto out_put;
-+
-+ return(sb);
-+
-+ out_put:
-+ iput(root_inode);
-+ out_dput:
-+ dput(proc_sb->s_root);
-+ out:
-+ return(NULL);
-+}
-+
-+DECLARE_FSTYPE(hppfs_type, "hppfs", hppfs_read_super, 0);
-+
-+static int __init init_hppfs(void)
-+{
-+ return(register_filesystem(&hppfs_type));
-+}
-+
-+static void __exit exit_hppfs(void)
-+{
-+ unregister_filesystem(&hppfs_type);
-+}
-+
-+module_init(init_hppfs)
-+module_exit(exit_hppfs)
-+MODULE_LICENSE("GPL");
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/fs/hppfs/Makefile um/arch/um/fs/hppfs/Makefile
---- orig/arch/um/fs/hppfs/Makefile 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/fs/hppfs/Makefile 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,10 @@
-+O_TARGET := hppfs.o
-+obj-y = hppfs_kern.o #hppfs_user.o
-+obj-m = $(O_TARGET)
-+
-+CFLAGS_hppfs_kern.o := $(CFLAGS)
-+#CFLAGS_hppfs_user.o := $(USER_CFLAGS)
-+
-+override CFLAGS =
-+
-+include $(TOPDIR)/Rules.make
-diff -Naur -X ../exclude-files orig/arch/um/fs/Makefile um/arch/um/fs/Makefile
---- orig/arch/um/fs/Makefile 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/fs/Makefile 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,23 @@
-+#
-+# Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+# Licensed under the GPL
-+#
-+
-+O_TARGET := built-in.o
-+
-+subdir-y =
-+subdir-m =
-+
-+subdir-$(CONFIG_HOSTFS) += hostfs
-+subdir-$(CONFIG_HPPFS) += hppfs
-+
-+obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
-+obj-m += $(join $(subdir-m),$(subdir-m:%=/%.o))
-+
-+include $(TOPDIR)/Rules.make
-+
-+dep:
-+
-+clean:
-+
-+archmrproper:
-diff -Naur -X ../exclude-files orig/arch/um/include/2_5compat.h um/arch/um/include/2_5compat.h
---- orig/arch/um/include/2_5compat.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/2_5compat.h 2003-11-07 02:49:26.000000000 -0500
-@@ -0,0 +1,33 @@
-+/*
-+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __2_5_COMPAT_H__
-+#define __2_5_COMPAT_H__
-+
-+#include "linux/version.h"
-+
-+#define INIT_ELV(queue, elv) elevator_init(elv, ELV_NOOP)
-+
-+#define ELV_NOOP ELEVATOR_NOOP
-+
-+#define INIT_HARDSECT(arr, maj, sizes) arr[maj] = sizes
-+
-+#define IS_WRITE(req) ((req)->cmd == WRITE)
-+
-+#define SET_PRI(task) \
-+ do { (task)->nice = 20; (task)->counter = -100; } while(0);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/chan_kern.h um/arch/um/include/chan_kern.h
---- orig/arch/um/include/chan_kern.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/chan_kern.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,56 @@
-+/*
-+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __CHAN_KERN_H__
-+#define __CHAN_KERN_H__
-+
-+#include "linux/tty.h"
-+#include "linux/list.h"
-+#include "chan_user.h"
-+
-+struct chan {
-+ struct list_head list;
-+ char *dev;
-+ unsigned int primary:1;
-+ unsigned int input:1;
-+ unsigned int output:1;
-+ unsigned int opened:1;
-+ int fd;
-+ enum chan_init_pri pri;
-+ struct chan_ops *ops;
-+ void *data;
-+};
-+
-+extern void chan_interrupt(struct list_head *chans, struct tq_struct *task,
-+ struct tty_struct *tty, int irq, void *dev);
-+extern int parse_chan_pair(char *str, struct list_head *chans, int pri,
-+ int device, struct chan_opts *opts);
-+extern int open_chan(struct list_head *chans);
-+extern int write_chan(struct list_head *chans, const char *buf, int len,
-+ int write_irq);
-+extern int console_write_chan(struct list_head *chans, const char *buf,
-+ int len);
-+extern void close_chan(struct list_head *chans);
-+extern void chan_enable_winch(struct list_head *chans, void *line);
-+extern void enable_chan(struct list_head *chans, void *data);
-+extern int chan_window_size(struct list_head *chans,
-+ unsigned short *rows_out,
-+ unsigned short *cols_out);
-+extern int chan_out_fd(struct list_head *chans);
-+extern int chan_config_string(struct list_head *chans, char *str, int size,
-+ char **error_out);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/chan_user.h um/arch/um/include/chan_user.h
---- orig/arch/um/include/chan_user.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/chan_user.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,66 @@
-+/*
-+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __CHAN_USER_H__
-+#define __CHAN_USER_H__
-+
-+#include "init.h"
-+
-+struct chan_opts {
-+ void (*announce)(char *dev_name, int dev);
-+ char *xterm_title;
-+ int raw;
-+ unsigned long tramp_stack;
-+ int in_kernel;
-+};
-+
-+enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
-+
-+struct chan_ops {
-+ char *type;
-+ void *(*init)(char *, int, struct chan_opts *);
-+ int (*open)(int, int, int, void *, char **);
-+ void (*close)(int, void *);
-+ int (*read)(int, char *, void *);
-+ int (*write)(int, const char *, int, void *);
-+ int (*console_write)(int, const char *, int, void *);
-+ int (*window_size)(int, void *, unsigned short *, unsigned short *);
-+ void (*free)(void *);
-+ int winch;
-+};
-+
-+extern struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops, tty_ops,
-+ xterm_ops;
-+
-+extern void generic_close(int fd, void *unused);
-+extern int generic_read(int fd, char *c_out, void *unused);
-+extern int generic_write(int fd, const char *buf, int n, void *unused);
-+extern int generic_console_write(int fd, const char *buf, int n, void *state);
-+extern int generic_window_size(int fd, void *unused, unsigned short *rows_out,
-+ unsigned short *cols_out);
-+extern void generic_free(void *data);
-+
-+extern void register_winch(int fd, void *device_data);
-+extern void register_winch_irq(int fd, int tty_fd, int pid, void *line);
-+
-+#define __channel_help(fn, prefix) \
-+__uml_help(fn, prefix "[0-9]*=<channel description>\n" \
-+" Attach a console or serial line to a host channel. See\n" \
-+" http://user-mode-linux.sourceforge.net/input.html for a complete\n" \
-+" description of this switch.\n\n" \
-+);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/choose-mode.h um/arch/um/include/choose-mode.h
---- orig/arch/um/include/choose-mode.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/choose-mode.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,35 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __CHOOSE_MODE_H__
-+#define __CHOOSE_MODE_H__
-+
-+#include "uml-config.h"
-+
-+#if defined(UML_CONFIG_MODE_TT) && defined(UML_CONFIG_MODE_SKAS)
-+#define CHOOSE_MODE(tt, skas) (mode_tt ? (tt) : (skas))
-+
-+#elif defined(UML_CONFIG_MODE_SKAS)
-+#define CHOOSE_MODE(tt, skas) (skas)
-+
-+#elif defined(UML_CONFIG_MODE_TT)
-+#define CHOOSE_MODE(tt, skas) (tt)
-+#endif
-+
-+#define CHOOSE_MODE_PROC(tt, skas, args...) \
-+ CHOOSE_MODE(tt(args), skas(args))
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/frame.h um/arch/um/include/frame.h
---- orig/arch/um/include/frame.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/frame.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,53 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __FRAME_H_
-+#define __FRAME_H_
-+
-+#include "sysdep/frame.h"
-+
-+struct frame_common {
-+ void *data;
-+ int len;
-+ int sig_index;
-+ int sr_index;
-+ int sr_relative;
-+ int sp_index;
-+ struct arch_frame_data arch;
-+};
-+
-+struct sc_frame {
-+ struct frame_common common;
-+ int sc_index;
-+};
-+
-+extern struct sc_frame signal_frame_sc;
-+
-+extern struct sc_frame signal_frame_sc_sr;
-+
-+struct si_frame {
-+ struct frame_common common;
-+ int sip_index;
-+ int si_index;
-+ int ucp_index;
-+ int uc_index;
-+};
-+
-+extern struct si_frame signal_frame_si;
-+
-+extern void capture_signal_stack(void);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/frame_kern.h um/arch/um/include/frame_kern.h
---- orig/arch/um/include/frame_kern.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/frame_kern.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,34 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __FRAME_KERN_H_
-+#define __FRAME_KERN_H_
-+
-+#include "frame.h"
-+#include "sysdep/frame_kern.h"
-+
-+extern int setup_signal_stack_sc(unsigned long stack_top, int sig,
-+ unsigned long handler,
-+ void (*restorer)(void),
-+ struct pt_regs *regs,
-+ sigset_t *mask);
-+extern int setup_signal_stack_si(unsigned long stack_top, int sig,
-+ unsigned long handler,
-+ void (*restorer)(void),
-+ struct pt_regs *regs, siginfo_t *info,
-+ sigset_t *mask);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/frame_user.h um/arch/um/include/frame_user.h
---- orig/arch/um/include/frame_user.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/frame_user.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,23 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __FRAME_USER_H_
-+#define __FRAME_USER_H_
-+
-+#include "sysdep/frame_user.h"
-+#include "frame.h"
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/helper.h um/arch/um/include/helper.h
---- orig/arch/um/include/helper.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/helper.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,27 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __HELPER_H__
-+#define __HELPER_H__
-+
-+extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
-+ unsigned long *stack_out);
-+extern int run_helper_thread(int (*proc)(void *), void *arg,
-+ unsigned int flags, unsigned long *stack_out,
-+ int stack_order);
-+extern int helper_wait(int pid);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/init.h um/arch/um/include/init.h
---- orig/arch/um/include/init.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/init.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,114 @@
-+#ifndef _LINUX_UML_INIT_H
-+#define _LINUX_UML_INIT_H
-+
-+/* These macros are used to mark some functions or
-+ * initialized data (doesn't apply to uninitialized data)
-+ * as `initialization' functions. The kernel can take this
-+ * as hint that the function is used only during the initialization
-+ * phase and free up used memory resources after
-+ *
-+ * Usage:
-+ * For functions:
-+ *
-+ * You should add __init immediately before the function name, like:
-+ *
-+ * static void __init initme(int x, int y)
-+ * {
-+ * extern int z; z = x * y;
-+ * }
-+ *
-+ * If the function has a prototype somewhere, you can also add
-+ * __init between closing brace of the prototype and semicolon:
-+ *
-+ * extern int initialize_foobar_device(int, int, int) __init;
-+ *
-+ * For initialized data:
-+ * You should insert __initdata between the variable name and equal
-+ * sign followed by value, e.g.:
-+ *
-+ * static int init_variable __initdata = 0;
-+ * static char linux_logo[] __initdata = { 0x32, 0x36, ... };
-+ *
-+ * Don't forget to initialize data not at file scope, i.e. within a function,
-+ * as gcc otherwise puts the data into the bss section and not into the init
-+ * section.
-+ *
-+ * Also note, that this data cannot be "const".
-+ */
-+
-+#ifndef _LINUX_INIT_H
-+typedef int (*initcall_t)(void);
-+typedef void (*exitcall_t)(void);
-+
-+#define __init __attribute__ ((__section__ (".text.init")))
-+#define __exit __attribute__ ((unused, __section__(".text.exit")))
-+#define __initdata __attribute__ ((__section__ (".data.init")))
-+
-+#endif
-+
-+#ifndef MODULE
-+struct uml_param {
-+ const char *str;
-+ int (*setup_func)(char *, int *);
-+};
-+
-+extern initcall_t __uml_initcall_start, __uml_initcall_end;
-+extern initcall_t __uml_postsetup_start, __uml_postsetup_end;
-+extern const char *__uml_help_start, *__uml_help_end;
-+#endif
-+
-+#define __uml_initcall(fn) \
-+ static initcall_t __uml_initcall_##fn __uml_init_call = fn
-+
-+#define __uml_exitcall(fn) \
-+ static exitcall_t __uml_exitcall_##fn __uml_exit_call = fn
-+
-+extern struct uml_param __uml_setup_start, __uml_setup_end;
-+
-+#define __uml_postsetup(fn) \
-+ static initcall_t __uml_postsetup_##fn __uml_postsetup_call = fn
-+
-+#define __non_empty_string(dummyname,string) \
-+ struct __uml_non_empty_string_struct_##dummyname \
-+ { \
-+ char _string[sizeof(string)-2]; \
-+ }
-+
-+#ifndef MODULE
-+#define __uml_setup(str, fn, help...) \
-+ __non_empty_string(fn ##_setup, str); \
-+ __uml_help(fn, help); \
-+ static char __uml_setup_str_##fn[] __initdata = str; \
-+ static struct uml_param __uml_setup_##fn __uml_init_setup = { __uml_setup_str_##fn, fn }
-+#else
-+#define __uml_setup(str, fn, help...) \
-+
-+#endif
-+
-+#define __uml_help(fn, help...) \
-+ __non_empty_string(fn ##__help, help); \
-+ static char __uml_help_str_##fn[] __initdata = help; \
-+ static const char *__uml_help_##fn __uml_setup_help = __uml_help_str_##fn
-+
-+/*
-+ * Mark functions and data as being only used at initialization
-+ * or exit time.
-+ */
-+#define __uml_init_setup __attribute__ ((unused,__section__ (".uml.setup.init")))
-+#define __uml_setup_help __attribute__ ((unused,__section__ (".uml.help.init")))
-+#define __uml_init_call __attribute__ ((unused,__section__ (".uml.initcall.init")))
-+#define __uml_postsetup_call __attribute__ ((unused,__section__ (".uml.postsetup.init")))
-+#define __uml_exit_call __attribute__ ((unused,__section__ (".uml.exitcall.exit")))
-+
-+#endif /* _LINUX_UML_INIT_H */
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/initrd.h um/arch/um/include/initrd.h
---- orig/arch/um/include/initrd.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/initrd.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,22 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __INITRD_USER_H__
-+#define __INITRD_USER_H__
-+
-+extern int load_initrd(char *filename, void *buf, int size);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/irq_kern.h um/arch/um/include/irq_kern.h
---- orig/arch/um/include/irq_kern.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/irq_kern.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,27 @@
-+/*
-+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __IRQ_KERN_H__
-+#define __IRQ_KERN_H__
-+
-+#include "linux/interrupt.h"
-+
-+extern int um_request_irq(unsigned int irq, int fd, int type,
-+ void (*handler)(int, void *, struct pt_regs *),
-+ unsigned long irqflags, const char * devname,
-+ void *dev_id);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/irq_user.h um/arch/um/include/irq_user.h
---- orig/arch/um/include/irq_user.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/irq_user.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,35 @@
-+/*
-+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __IRQ_USER_H__
-+#define __IRQ_USER_H__
-+
-+enum { IRQ_READ, IRQ_WRITE };
-+
-+extern void sigio_handler(int sig, union uml_pt_regs *regs);
-+extern int activate_fd(int irq, int fd, int type, void *dev_id);
-+extern void free_irq_by_irq_and_dev(int irq, void *dev_id);
-+extern void free_irq_by_fd(int fd);
-+extern void reactivate_fd(int fd, int irqnum);
-+extern void deactivate_fd(int fd, int irqnum);
-+extern void forward_interrupts(int pid);
-+extern void init_irq_signals(int on_sigstack);
-+extern void forward_ipi(int fd, int pid);
-+extern void free_irq_later(int irq, void *dev_id);
-+extern int activate_ipi(int fd, int pid);
-+extern unsigned long irq_lock(void);
-+extern void irq_unlock(unsigned long flags);
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/kern.h um/arch/um/include/kern.h
---- orig/arch/um/include/kern.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/kern.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,48 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __KERN_H__
-+#define __KERN_H__
-+
-+/* These are all user-mode things which are convenient to call directly
-+ * from kernel code and for which writing a wrapper is too much of a pain.
-+ * The regular include files can't be included because this file is included
-+ * only into kernel code, and user-space includes conflict with kernel
-+ * includes.
-+ */
-+
-+extern int errno;
-+
-+extern int clone(int (*proc)(void *), void *sp, int flags, void *data);
-+extern int sleep(int);
-+extern int printf(char *fmt, ...);
-+extern char *strerror(int errnum);
-+extern char *ptsname(int __fd);
-+extern int munmap(void *, int);
-+extern void *sbrk(int increment);
-+extern void *malloc(int size);
-+extern void perror(char *err);
-+extern int kill(int pid, int sig);
-+extern int getuid(void);
-+extern int pause(void);
-+extern int write(int, const void *, int);
-+extern int exit(int);
-+extern int close(int);
-+extern int read(unsigned int, char *, int);
-+extern int pipe(int *);
-+extern int sched_yield(void);
-+extern int ptrace(int op, int pid, long addr, long data);
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/kern_util.h um/arch/um/include/kern_util.h
---- orig/arch/um/include/kern_util.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/kern_util.h 2003-11-10 00:58:10.000000000 -0500
-@@ -0,0 +1,123 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __KERN_UTIL_H__
-+#define __KERN_UTIL_H__
-+
-+#include "sysdep/ptrace.h"
-+
-+extern int ncpus;
-+extern char *linux_prog;
-+extern char *gdb_init;
-+extern int kmalloc_ok;
-+extern int timer_irq_inited;
-+extern int jail;
-+extern int nsyscalls;
-+
-+#define UML_ROUND_DOWN(addr) ((void *)(((unsigned long) addr) & PAGE_MASK))
-+#define UML_ROUND_UP(addr) \
-+ UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1)
-+
-+extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg);
-+extern unsigned long stack_sp(unsigned long page);
-+extern int kernel_thread_proc(void *data);
-+extern void syscall_segv(int sig);
-+extern int current_pid(void);
-+extern unsigned long alloc_stack(int order, int atomic);
-+extern int do_signal(int error);
-+extern int is_stack_fault(unsigned long sp);
-+extern unsigned long segv(unsigned long address, unsigned long ip,
-+ int is_write, int is_user, void *sc);
-+extern unsigned long handle_page_fault(unsigned long address, unsigned long ip,
-+ int is_write, int is_user,
-+ int *code_out);
-+extern void syscall_ready(void);
-+extern int segv_syscall(void);
-+extern void kern_finish_exec(void *task, int new_pid, unsigned long stack);
-+extern int page_size(void);
-+extern int page_mask(void);
-+extern int need_finish_fork(void);
-+extern void free_stack(unsigned long stack, int order);
-+extern void add_input_request(int op, void (*proc)(int), void *arg);
-+extern int sys_execve(char *file, char **argv, char **env);
-+extern char *current_cmd(void);
-+extern void timer_handler(int sig, union uml_pt_regs *regs);
-+extern int set_signals(int enable);
-+extern void force_sigbus(void);
-+extern int pid_to_processor_id(int pid);
-+extern void block_signals(void);
-+extern void unblock_signals(void);
-+extern void deliver_signals(void *t);
-+extern int next_syscall_index(int max);
-+extern int next_trap_index(int max);
-+extern void cpu_idle(void);
-+extern void finish_fork(void);
-+extern void paging_init(void);
-+extern void init_flush_vm(void);
-+extern void *syscall_sp(void *t);
-+extern void syscall_trace(void);
-+extern int hz(void);
-+extern void idle_timer(void);
-+extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs);
-+extern int external_pid(void *t);
-+extern void boot_timer_handler(int sig);
-+extern void interrupt_end(void);
-+extern void initial_thread_cb(void (*proc)(void *), void *arg);
-+extern int debugger_signal(int status, int pid);
-+extern void debugger_parent_signal(int status, int pid);
-+extern void child_signal(int pid, int status);
-+extern int init_ptrace_proxy(int idle_pid, int startup, int stop);
-+extern int init_parent_proxy(int pid);
-+extern void check_stack_overflow(void *ptr);
-+extern void relay_signal(int sig, union uml_pt_regs *regs);
-+extern void not_implemented(void);
-+extern int user_context(unsigned long sp);
-+extern void timer_irq(union uml_pt_regs *regs);
-+extern void unprotect_stack(unsigned long stack);
-+extern void do_uml_exitcalls(void);
-+extern int attach_debugger(int idle_pid, int pid, int stop);
-+extern void bad_segv(unsigned long address, unsigned long ip, int is_write);
-+extern int config_gdb(char *str);
-+extern int remove_gdb(void);
-+extern char *uml_strdup(char *string);
-+extern void unprotect_kernel_mem(void);
-+extern void protect_kernel_mem(void);
-+extern void set_kmem_end(unsigned long);
-+extern void uml_cleanup(void);
-+extern void set_current(void *t);
-+extern void lock_signalled_task(void *t);
-+extern void IPI_handler(int cpu);
-+extern int jail_setup(char *line, int *add);
-+extern void *get_init_task(void);
-+extern int clear_user_proc(void *buf, int size);
-+extern int copy_to_user_proc(void *to, void *from, int size);
-+extern int copy_from_user_proc(void *to, void *from, int size);
-+extern int strlen_user_proc(char *str);
-+extern void bus_handler(int sig, union uml_pt_regs *regs);
-+extern void winch(int sig, union uml_pt_regs *regs);
-+extern long execute_syscall(void *r);
-+extern int smp_sigio_handler(void);
-+extern void *get_current(void);
-+extern struct task_struct *get_task(int pid, int require);
-+extern void machine_halt(void);
-+extern int is_syscall(unsigned long addr);
-+extern void arch_switch(void);
-+extern void free_irq(unsigned int, void *);
-+extern int um_in_interrupt(void);
-+extern int cpu(void);
-+extern unsigned long long time_stamp(void);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/line.h um/arch/um/include/line.h
---- orig/arch/um/include/line.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/line.h 2003-11-07 02:25:37.000000000 -0500
-@@ -0,0 +1,103 @@
-+/*
-+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __LINE_H__
-+#define __LINE_H__
-+
-+#include "linux/list.h"
-+#include "linux/tqueue.h"
-+#include "linux/tty.h"
-+#include "asm/semaphore.h"
-+#include "chan_user.h"
-+#include "mconsole_kern.h"
-+
-+struct line_driver {
-+ char *name;
-+ char *devfs_name;
-+ short major;
-+ short minor_start;
-+ short type;
-+ short subtype;
-+ int read_irq;
-+ char *read_irq_name;
-+ int write_irq;
-+ char *write_irq_name;
-+ char *symlink_from;
-+ char *symlink_to;
-+ struct mc_device mc;
-+};
-+
-+struct line {
-+ char *init_str;
-+ int init_pri;
-+ struct list_head chan_list;
-+ int valid;
-+ int count;
-+ struct tty_struct *tty;
-+ struct semaphore sem;
-+ char *buffer;
-+ char *head;
-+ char *tail;
-+ int sigio;
-+ struct tq_struct task;
-+ struct line_driver *driver;
-+ int have_irq;
-+};
-+
-+#define LINE_INIT(str, d) \
-+ { init_str : str, \
-+ init_pri : INIT_STATIC, \
-+ chan_list : { }, \
-+ valid : 1, \
-+ count : 0, \
-+ tty : NULL, \
-+ sem : { }, \
-+ buffer : NULL, \
-+ head : NULL, \
-+ tail : NULL, \
-+ sigio : 0, \
-+ driver : d, \
-+ have_irq : 0 }
-+
-+struct lines {
-+ int num;
-+};
-+
-+#define LINES_INIT(n) { num : n }
-+
-+extern void line_close(struct line *lines, struct tty_struct *tty);
-+extern int line_open(struct line *lines, struct tty_struct *tty,
-+ struct chan_opts *opts);
-+extern int line_setup(struct line *lines, int num, char *init,
-+ int all_allowed);
-+extern int line_write(struct line *line, struct tty_struct *tty, int from_user,
-+ const char *buf, int len);
-+extern char *add_xterm_umid(char *base);
-+extern int line_setup_irq(int fd, int input, int output, void *data);
-+extern void line_close_chan(struct line *line);
-+extern void line_disable(struct line *line, int current_irq);
-+extern void line_register_devfs(struct lines *set,
-+ struct line_driver *line_driver,
-+ struct tty_driver *driver, struct line *lines,
-+ int nlines);
-+extern void lines_init(struct line *lines, int nlines);
-+extern void close_lines(struct line *lines, int nlines);
-+extern int line_config(struct line *lines, int num, char *str);
-+extern int line_remove(struct line *lines, int num, char *str);
-+extern int line_get_config(char *dev, struct line *lines, int num, char *str,
-+ int size, char **error_out);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/Makefile um/arch/um/include/Makefile
---- orig/arch/um/include/Makefile 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/Makefile 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,7 @@
-+all : sc.h
-+
-+sc.h : ../util/mk_sc
-+ ../util/mk_sc > $@
-+
-+../util/mk_sc :
-+ $(MAKE) -C ../util mk_sc
-diff -Naur -X ../exclude-files orig/arch/um/include/mconsole.h um/arch/um/include/mconsole.h
---- orig/arch/um/include/mconsole.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/mconsole.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,103 @@
-+/*
-+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
-+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __MCONSOLE_H__
-+#define __MCONSOLE_H__
-+
-+#ifndef __KERNEL__
-+#include <stdint.h>
-+#define u32 uint32_t
-+#endif
-+
-+#define MCONSOLE_MAGIC (0xcafebabe)
-+#define MCONSOLE_MAX_DATA (512)
-+#define MCONSOLE_VERSION 2
-+
-+struct mconsole_request {
-+ u32 magic;
-+ u32 version;
-+ u32 len;
-+ char data[MCONSOLE_MAX_DATA];
-+};
-+
-+struct mconsole_reply {
-+ u32 err;
-+ u32 more;
-+ u32 len;
-+ char data[MCONSOLE_MAX_DATA];
-+};
-+
-+struct mconsole_notify {
-+ u32 magic;
-+ u32 version;
-+ enum { MCONSOLE_SOCKET, MCONSOLE_PANIC, MCONSOLE_HANG,
-+ MCONSOLE_USER_NOTIFY } type;
-+ u32 len;
-+ char data[MCONSOLE_MAX_DATA];
-+};
-+
-+struct mc_request;
-+
-+enum mc_context { MCONSOLE_INTR, MCONSOLE_PROC };
-+
-+struct mconsole_command
-+{
-+ char *command;
-+ void (*handler)(struct mc_request *req);
-+ enum mc_context context;
-+};
-+
-+struct mc_request
-+{
-+ int len;
-+ int as_interrupt;
-+
-+ int originating_fd;
-+ int originlen;
-+ unsigned char origin[128]; /* sockaddr_un */
-+
-+ struct mconsole_request request;
-+ struct mconsole_command *cmd;
-+};
-+
-+extern char mconsole_socket_name[];
-+
-+extern int mconsole_unlink_socket(void);
-+extern int mconsole_reply(struct mc_request *req, char *reply, int err,
-+ int more);
-+
-+extern void mconsole_version(struct mc_request *req);
-+extern void mconsole_help(struct mc_request *req);
-+extern void mconsole_halt(struct mc_request *req);
-+extern void mconsole_reboot(struct mc_request *req);
-+extern void mconsole_config(struct mc_request *req);
-+extern void mconsole_remove(struct mc_request *req);
-+extern void mconsole_sysrq(struct mc_request *req);
-+extern void mconsole_cad(struct mc_request *req);
-+extern void mconsole_stop(struct mc_request *req);
-+extern void mconsole_go(struct mc_request *req);
-+extern void mconsole_log(struct mc_request *req);
-+extern void mconsole_proc(struct mc_request *req);
-+
-+extern int mconsole_get_request(int fd, struct mc_request *req);
-+extern int mconsole_notify(char *sock_name, int type, const void *data,
-+ int len);
-+extern char *mconsole_notify_socket(void);
-+extern void lock_notify(void);
-+extern void unlock_notify(void);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/mconsole_kern.h um/arch/um/include/mconsole_kern.h
---- orig/arch/um/include/mconsole_kern.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/mconsole_kern.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,62 @@
-+/*
-+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __MCONSOLE_KERN_H__
-+#define __MCONSOLE_KERN_H__
-+
-+#include "linux/config.h"
-+#include "linux/list.h"
-+#include "mconsole.h"
-+
-+struct mconsole_entry {
-+ struct list_head list;
-+ struct mc_request request;
-+};
-+
-+struct mc_device {
-+ struct list_head list;
-+ char *name;
-+ int (*config)(char *);
-+ int (*get_config)(char *, char *, int, char **);
-+ int (*remove)(char *);
-+};
-+
-+#define CONFIG_CHUNK(str, size, current, chunk, end) \
-+do { \
-+ current += strlen(chunk); \
-+ if(current >= size) \
-+ str = NULL; \
-+ if(str != NULL){ \
-+ strcpy(str, chunk); \
-+ str += strlen(chunk); \
-+ } \
-+ if(end) \
-+ current++; \
-+} while(0)
-+
-+#ifdef CONFIG_MCONSOLE
-+
-+extern void mconsole_register_dev(struct mc_device *new);
-+
-+#else
-+
-+static inline void mconsole_register_dev(struct mc_device *new)
-+{
-+}
-+
-+#endif
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/mem.h um/arch/um/include/mem.h
---- orig/arch/um/include/mem.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/mem.h 2004-01-16 11:14:38.000000000 -0500
-@@ -0,0 +1,29 @@
-+/*
-+ * Copyright (C) 2002, 2003 Jeff Dike (jdike@addtoit.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __MEM_H__
-+#define __MEM_H__
-+
-+#include "linux/types.h"
-+
-+extern void set_kmem_end(unsigned long new);
-+extern int phys_mapping(unsigned long phys, __u64 *offset_out);
-+extern int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w);
-+extern int is_remapped(void *virt);
-+extern int physmem_remove_mapping(void *virt);
-+extern void physmem_forget_descriptor(int fd);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/mem_kern.h um/arch/um/include/mem_kern.h
---- orig/arch/um/include/mem_kern.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/mem_kern.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,30 @@
-+/*
-+ * Copyright (C) 2003 Jeff Dike (jdike@addtoit.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __MEM_KERN_H__
-+#define __MEM_KERN_H__
-+
-+#include "linux/list.h"
-+#include "linux/types.h"
-+
-+struct remapper {
-+ struct list_head list;
-+ int (*proc)(int, unsigned long, int, __u64);
-+};
-+
-+extern void register_remapper(struct remapper *info);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/mem_user.h um/arch/um/include/mem_user.h
---- orig/arch/um/include/mem_user.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/mem_user.h 2004-01-10 00:11:06.000000000 -0500
-@@ -0,0 +1,81 @@
-+/*
-+ * arch/um/include/mem_user.h
-+ *
-+ * BRIEF MODULE DESCRIPTION
-+ * user side memory interface for support IO memory inside user mode linux
-+ *
-+ * Copyright (C) 2001 RidgeRun, Inc.
-+ * Author: RidgeRun, Inc.
-+ * Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the
-+ * Free Software Foundation; either version 2 of the License, or (at your
-+ * option) any later version.
-+ *
-+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
-+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
-+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ *
-+ * 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.,
-+ * 675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
-+
-+#ifndef _MEM_USER_H
-+#define _MEM_USER_H
-+
-+struct iomem_region {
-+ struct iomem_region *next;
-+ char *driver;
-+ int fd;
-+ int size;
-+ unsigned long phys;
-+ unsigned long virt;
-+};
-+
-+extern struct iomem_region *iomem_regions;
-+extern int iomem_size;
-+
-+#define ROUND_4M(n) ((((unsigned long) (n)) + (1 << 22)) & ~((1 << 22) - 1))
-+
-+extern unsigned long host_task_size;
-+extern unsigned long task_size;
-+
-+extern int init_mem_user(void);
-+extern int create_mem_file(unsigned long len);
-+extern void setup_memory(void *entry);
-+extern unsigned long find_iomem(char *driver, unsigned long *len_out);
-+extern int init_maps(unsigned long physmem, unsigned long iomem,
-+ unsigned long highmem);
-+extern unsigned long get_vm(unsigned long len);
-+extern void setup_physmem(unsigned long start, unsigned long usable,
-+ unsigned long len, unsigned long highmem);
-+extern void add_iomem(char *name, int fd, unsigned long size);
-+extern unsigned long phys_offset(unsigned long phys);
-+extern void unmap_physmem(void);
-+extern void map_memory(unsigned long virt, unsigned long phys,
-+ unsigned long len, int r, int w, int x);
-+extern int protect_memory(unsigned long addr, unsigned long len,
-+ int r, int w, int x, int must_succeed);
-+extern unsigned long get_kmem_end(void);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/mode.h um/arch/um/include/mode.h
---- orig/arch/um/include/mode.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/mode.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,30 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __MODE_H__
-+#define __MODE_H__
-+
-+#include "uml-config.h"
-+
-+#ifdef UML_CONFIG_MODE_TT
-+#include "../kernel/tt/include/mode.h"
-+#endif
-+
-+#ifdef UML_CONFIG_MODE_SKAS
-+#include "../kernel/skas/include/mode.h"
-+#endif
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/mode_kern.h um/arch/um/include/mode_kern.h
---- orig/arch/um/include/mode_kern.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/mode_kern.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,30 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __MODE_KERN_H__
-+#define __MODE_KERN_H__
-+
-+#include "linux/config.h"
-+
-+#ifdef CONFIG_MODE_TT
-+#include "../kernel/tt/include/mode_kern.h"
-+#endif
-+
-+#ifdef CONFIG_MODE_SKAS
-+#include "../kernel/skas/include/mode_kern.h"
-+#endif
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/net_kern.h um/arch/um/include/net_kern.h
---- orig/arch/um/include/net_kern.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/net_kern.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,81 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UM_NET_KERN_H
-+#define __UM_NET_KERN_H
-+
-+#include "linux/netdevice.h"
-+#include "linux/skbuff.h"
-+#include "linux/socket.h"
-+#include "linux/list.h"
-+
-+struct uml_net {
-+ struct list_head list;
-+ struct net_device *dev;
-+ int index;
-+ unsigned char mac[ETH_ALEN];
-+ int have_mac;
-+};
-+
-+struct uml_net_private {
-+ struct list_head list;
-+ spinlock_t lock;
-+ struct net_device *dev;
-+ struct timer_list tl;
-+ struct net_device_stats stats;
-+ int fd;
-+ unsigned char mac[ETH_ALEN];
-+ int have_mac;
-+ unsigned short (*protocol)(struct sk_buff *);
-+ int (*open)(void *);
-+ void (*close)(int, void *);
-+ void (*remove)(void *);
-+ int (*read)(int, struct sk_buff **skb, struct uml_net_private *);
-+ int (*write)(int, struct sk_buff **skb, struct uml_net_private *);
-+
-+ void (*add_address)(unsigned char *, unsigned char *, void *);
-+ void (*delete_address)(unsigned char *, unsigned char *, void *);
-+ int (*set_mtu)(int mtu, void *);
-+ int user[1];
-+};
-+
-+struct net_kern_info {
-+ void (*init)(struct net_device *, void *);
-+ unsigned short (*protocol)(struct sk_buff *);
-+ int (*read)(int, struct sk_buff **skb, struct uml_net_private *);
-+ int (*write)(int, struct sk_buff **skb, struct uml_net_private *);
-+};
-+
-+struct transport {
-+ struct list_head list;
-+ char *name;
-+ int (*setup)(char *, char **, void *);
-+ struct net_user_info *user;
-+ struct net_kern_info *kern;
-+ int private_size;
-+ int setup_size;
-+};
-+
-+extern struct net_device *ether_init(int);
-+extern unsigned short ether_protocol(struct sk_buff *);
-+extern int setup_etheraddr(char *str, unsigned char *addr);
-+extern struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra);
-+extern int tap_setup_common(char *str, char *type, char **dev_name,
-+ char **mac_out, char **gate_addr);
-+extern void register_transport(struct transport *new);
-+extern unsigned short eth_protocol(struct sk_buff *skb);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/net_user.h um/arch/um/include/net_user.h
---- orig/arch/um/include/net_user.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/net_user.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,66 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UM_NET_USER_H__
-+#define __UM_NET_USER_H__
-+
-+#define ETH_ADDR_LEN (6)
-+#define ETH_HEADER_ETHERTAP (16)
-+#define ETH_HEADER_OTHER (14)
-+#define ETH_MAX_PACKET (1500)
-+
-+#define UML_NET_VERSION (4)
-+
-+struct net_user_info {
-+ void (*init)(void *, void *);
-+ int (*open)(void *);
-+ void (*close)(int, void *);
-+ void (*remove)(void *);
-+ int (*set_mtu)(int mtu, void *);
-+ void (*add_address)(unsigned char *, unsigned char *, void *);
-+ void (*delete_address)(unsigned char *, unsigned char *, void *);
-+ int max_packet;
-+};
-+
-+extern void ether_user_init(void *data, void *dev);
-+extern void dev_ip_addr(void *d, char *buf, char *bin_buf);
-+extern void set_ether_mac(void *d, unsigned char *addr);
-+extern void iter_addresses(void *d, void (*cb)(unsigned char *,
-+ unsigned char *, void *),
-+ void *arg);
-+
-+extern void *get_output_buffer(int *len_out);
-+extern void free_output_buffer(void *buffer);
-+
-+extern int tap_open_common(void *dev, char *gate_addr);
-+extern void tap_check_ips(char *gate_addr, char *eth_addr);
-+
-+extern void read_output(int fd, char *output_out, int len);
-+
-+extern int net_read(int fd, void *buf, int len);
-+extern int net_recvfrom(int fd, void *buf, int len);
-+extern int net_write(int fd, void *buf, int len);
-+extern int net_send(int fd, void *buf, int len);
-+extern int net_sendto(int fd, void *buf, int len, void *to, int sock_len);
-+
-+extern void open_addr(unsigned char *addr, unsigned char *netmask, void *arg);
-+extern void close_addr(unsigned char *addr, unsigned char *netmask, void *arg);
-+
-+extern char *split_if_spec(char *str, ...);
-+
-+extern int dev_netmask(void *d, void *m);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/os.h um/arch/um/include/os.h
---- orig/arch/um/include/os.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/os.h 2003-12-17 10:48:12.000000000 -0500
-@@ -0,0 +1,180 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __OS_H__
-+#define __OS_H__
-+
-+#include "asm/types.h"
-+#include "../os/include/file.h"
-+
-+#define OS_TYPE_FILE 1
-+#define OS_TYPE_DIR 2
-+#define OS_TYPE_SYMLINK 3
-+#define OS_TYPE_CHARDEV 4
-+#define OS_TYPE_BLOCKDEV 5
-+#define OS_TYPE_FIFO 6
-+#define OS_TYPE_SOCK 7
-+
-+/* os_access() flags */
-+#define OS_ACC_F_OK 0 /* Test for existence. */
-+#define OS_ACC_X_OK 1 /* Test for execute permission. */
-+#define OS_ACC_W_OK 2 /* Test for write permission. */
-+#define OS_ACC_R_OK 4 /* Test for read permission. */
-+#define OS_ACC_RW_OK (OS_ACC_W_OK | OS_ACC_R_OK) /* Test for RW permission */
-+
-+/*
-+ * types taken from stat_file() in hostfs_user.c
-+ * (if they are wrong here, they are wrong there...).
-+ */
-+struct uml_stat {
-+ int ust_dev; /* device */
-+ unsigned long long ust_ino; /* inode */
-+ int ust_mode; /* protection */
-+ int ust_nlink; /* number of hard links */
-+ int ust_uid; /* user ID of owner */
-+ int ust_gid; /* group ID of owner */
-+ unsigned long long ust_size; /* total size, in bytes */
-+ int ust_blksize; /* blocksize for filesystem I/O */
-+ unsigned long long ust_blocks; /* number of blocks allocated */
-+ unsigned long ust_atime; /* time of last access */
-+ unsigned long ust_mtime; /* time of last modification */
-+ unsigned long ust_ctime; /* time of last change */
-+};
-+
-+struct openflags {
-+ unsigned int r : 1;
-+ unsigned int w : 1;
-+ unsigned int s : 1; /* O_SYNC */
-+ unsigned int c : 1; /* O_CREAT */
-+ unsigned int t : 1; /* O_TRUNC */
-+ unsigned int a : 1; /* O_APPEND */
-+ unsigned int e : 1; /* O_EXCL */
-+ unsigned int cl : 1; /* FD_CLOEXEC */
-+};
-+
-+#define OPENFLAGS() ((struct openflags) { .r = 0, .w = 0, .s = 0, .c = 0, \
-+ .t = 0, .a = 0, .e = 0, .cl = 0 })
-+
-+static inline struct openflags of_read(struct openflags flags)
-+{
-+ flags.r = 1;
-+ return(flags);
-+}
-+
-+static inline struct openflags of_write(struct openflags flags)
-+{
-+ flags.w = 1;
-+ return(flags);
-+}
-+
-+static inline struct openflags of_rdwr(struct openflags flags)
-+{
-+ return(of_read(of_write(flags)));
-+}
-+
-+static inline struct openflags of_set_rw(struct openflags flags, int r, int w)
-+{
-+ flags.r = r;
-+ flags.w = w;
-+ return(flags);
-+}
-+
-+static inline struct openflags of_sync(struct openflags flags)
-+{
-+ flags.s = 1;
-+ return(flags);
-+}
-+
-+static inline struct openflags of_create(struct openflags flags)
-+{
-+ flags.c = 1;
-+ return(flags);
-+}
-+
-+static inline struct openflags of_trunc(struct openflags flags)
-+{
-+ flags.t = 1;
-+ return(flags);
-+}
-+
-+static inline struct openflags of_append(struct openflags flags)
-+{
-+ flags.a = 1;
-+ return(flags);
-+}
-+
-+static inline struct openflags of_excl(struct openflags flags)
-+{
-+ flags.e = 1;
-+ return(flags);
-+}
-+
-+static inline struct openflags of_cloexec(struct openflags flags)
-+{
-+ flags.cl = 1;
-+ return(flags);
-+}
-+
-+extern int os_stat_file(const char *file_name, struct uml_stat *buf);
-+extern int os_stat_fd(const int fd, struct uml_stat *buf);
-+extern int os_access(const char *file, int mode);
-+extern void os_print_error(int error, const char* str);
-+extern int os_get_exec_close(int fd, int *close_on_exec);
-+extern int os_set_exec_close(int fd, int close_on_exec);
-+extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg);
-+extern int os_window_size(int fd, int *rows, int *cols);
-+extern int os_new_tty_pgrp(int fd, int pid);
-+extern int os_get_ifname(int fd, char *namebuf);
-+extern int os_set_slip(int fd);
-+extern int os_set_owner(int fd, int pid);
-+extern int os_sigio_async(int master, int slave);
-+extern int os_mode_fd(int fd, int mode);
-+
-+extern int os_seek_file(int fd, __u64 offset);
-+extern int os_open_file(char *file, struct openflags flags, int mode);
-+extern int os_read_file(int fd, void *buf, int len);
-+extern int os_write_file(int fd, const void *buf, int count);
-+extern int os_file_size(char *file, long long *size_out);
-+extern int os_file_modtime(char *file, unsigned long *modtime);
-+extern int os_pipe(int *fd, int stream, int close_on_exec);
-+extern int os_set_fd_async(int fd, int owner);
-+extern int os_set_fd_block(int fd, int blocking);
-+extern int os_accept_connection(int fd);
-+extern int os_create_unix_socket(char *file, int len, int close_on_exec);
-+extern int os_shutdown_socket(int fd, int r, int w);
-+extern void os_close_file(int fd);
-+extern int os_rcv_fd(int fd, int *helper_pid_out);
-+extern int create_unix_socket(char *file, int len, int close_on_exec);
-+extern int os_connect_socket(char *name);
-+extern int os_file_type(char *file);
-+extern int os_file_mode(char *file, struct openflags *mode_out);
-+extern int os_lock_file(int fd, int excl);
-+
-+extern unsigned long os_process_pc(int pid);
-+extern int os_process_parent(int pid);
-+extern void os_stop_process(int pid);
-+extern void os_kill_process(int pid, int reap_child);
-+extern void os_usr1_process(int pid);
-+extern int os_getpid(void);
-+
-+extern int os_map_memory(void *virt, int fd, unsigned long long off,
-+ unsigned long len, int r, int w, int x);
-+extern int os_protect_memory(void *addr, unsigned long len,
-+ int r, int w, int x);
-+extern int os_unmap_memory(void *addr, int len);
-+extern void os_flush_stdout(void);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/process.h um/arch/um/include/process.h
---- orig/arch/um/include/process.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/process.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,25 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __PROCESS_H__
-+#define __PROCESS_H__
-+
-+#include <asm/sigcontext.h>
-+
-+extern void sig_handler(int sig, struct sigcontext sc);
-+extern void alarm_handler(int sig, struct sigcontext sc);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/ptrace_user.h um/arch/um/include/ptrace_user.h
---- orig/arch/um/include/ptrace_user.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/ptrace_user.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,18 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __PTRACE_USER_H__
-+#define __PTRACE_USER_H__
-+
-+#include "sysdep/ptrace_user.h"
-+
-+extern int ptrace_getregs(long pid, unsigned long *regs_out);
-+extern int ptrace_setregs(long pid, unsigned long *regs_in);
-+extern int ptrace_getfpregs(long pid, unsigned long *regs_out);
-+extern void arch_enter_kernel(void *task, int pid);
-+extern void arch_leave_kernel(void *task, int pid);
-+extern void ptrace_pokeuser(unsigned long addr, unsigned long data);
-+
-+#endif
-diff -Naur -X ../exclude-files orig/arch/um/include/sigcontext.h um/arch/um/include/sigcontext.h
---- orig/arch/um/include/sigcontext.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/sigcontext.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,25 @@
-+/*
-+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UML_SIGCONTEXT_H__
-+#define __UML_SIGCONTEXT_H__
-+
-+#include "sysdep/sigcontext.h"
-+
-+extern int sc_size(void *data);
-+extern void sc_to_sc(void *to_ptr, void *from_ptr);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/sigio.h um/arch/um/include/sigio.h
---- orig/arch/um/include/sigio.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/sigio.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,28 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __SIGIO_H__
-+#define __SIGIO_H__
-+
-+extern int write_sigio_irq(int fd);
-+extern int register_sigio_fd(int fd);
-+extern int read_sigio_fd(int fd);
-+extern int add_sigio_fd(int fd, int read);
-+extern int ignore_sigio_fd(int fd);
-+extern void sigio_lock(void);
-+extern void sigio_unlock(void);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/signal_kern.h um/arch/um/include/signal_kern.h
---- orig/arch/um/include/signal_kern.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/signal_kern.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,22 @@
-+/*
-+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __SIGNAL_KERN_H__
-+#define __SIGNAL_KERN_H__
-+
-+extern int have_signals(void *t);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/signal_user.h um/arch/um/include/signal_user.h
---- orig/arch/um/include/signal_user.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/signal_user.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,26 @@
-+/*
-+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __SIGNAL_USER_H__
-+#define __SIGNAL_USER_H__
-+
-+extern int signal_stack_size;
-+
-+extern int change_sig(int signal, int on);
-+extern void set_sigstack(void *stack, int size);
-+extern void set_handler(int sig, void (*handler)(int), int flags, ...);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/skas_ptrace.h um/arch/um/include/skas_ptrace.h
---- orig/arch/um/include/skas_ptrace.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/skas_ptrace.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,36 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __SKAS_PTRACE_H
-+#define __SKAS_PTRACE_H
-+
-+struct ptrace_faultinfo {
-+ int is_write;
-+ unsigned long addr;
-+};
-+
-+struct ptrace_ldt {
-+ int func;
-+ void *ptr;
-+ unsigned long bytecount;
-+};
-+
-+#define PTRACE_FAULTINFO 52
-+#define PTRACE_SIGPENDING 53
-+#define PTRACE_LDT 54
-+#define PTRACE_SWITCH_MM 55
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/syscall_user.h um/arch/um/include/syscall_user.h
---- orig/arch/um/include/syscall_user.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/syscall_user.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,23 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __SYSCALL_USER_H
-+#define __SYSCALL_USER_H
-+
-+extern int record_syscall_start(int syscall);
-+extern void record_syscall_end(int index, int result);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/checksum.h um/arch/um/include/sysdep-i386/checksum.h
---- orig/arch/um/include/sysdep-i386/checksum.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/sysdep-i386/checksum.h 2004-01-13 23:40:05.000000000 -0500
-@@ -0,0 +1,218 @@
-+/*
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UM_SYSDEP_CHECKSUM_H
-+#define __UM_SYSDEP_CHECKSUM_H
-+
-+#include "linux/string.h"
-+#include "asm/uaccess.h"
-+
-+/*
-+ * computes the checksum of a memory block at buff, length len,
-+ * and adds in "sum" (32-bit)
-+ *
-+ * returns a 32-bit number suitable for feeding into itself
-+ * or csum_tcpudp_magic
-+ *
-+ * this function must be called with even lengths, except
-+ * for the last fragment, which may be odd
-+ *
-+ * it's best to have buff aligned on a 32-bit boundary
-+ */
-+unsigned int csum_partial(const unsigned char * buff, int len,
-+ unsigned int sum);
-+
-+/*
-+ * the same as csum_partial, but copies from src while it
-+ * checksums, and handles user-space pointer exceptions correctly, when needed.
-+ *
-+ * here even more important to align src and dst on a 32-bit (or even
-+ * better 64-bit) boundary
-+ */
-+
-+unsigned int csum_partial_copy_to(const char *src, char *dst, int len,
-+ int sum, int *err_ptr);
-+unsigned int csum_partial_copy_from(const char *src, char *dst, int len,
-+ int sum, int *err_ptr);
-+
-+/*
-+ * Note: when you get a NULL pointer exception here this means someone
-+ * passed in an incorrect kernel address to one of these functions.
-+ *
-+ * If you use these functions directly please don't forget the
-+ * verify_area().
-+ */
-+
-+static __inline__
-+unsigned int csum_partial_copy_nocheck(const char *src, char *dst,
-+ int len, int sum)
-+{
-+ memcpy(dst, src, len);
-+ return(csum_partial(dst, len, sum));
-+}
-+
-+static __inline__
-+unsigned int csum_partial_copy_from_user(const char *src, char *dst,
-+ int len, int sum, int *err_ptr)
-+{
-+ return csum_partial_copy_from(src, dst, len, sum, err_ptr);
-+}
-+
-+/*
-+ * These are the old (and unsafe) way of doing checksums, a warning message
-+ * will be printed if they are used and an exception occurs.
-+ *
-+ * these functions should go away after some time.
-+ */
-+
-+#define csum_partial_copy_fromuser csum_partial_copy_from_user
-+unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum);
-+
-+/*
-+ * This is a version of ip_compute_csum() optimized for IP headers,
-+ * which always checksum on 4 octet boundaries.
-+ *
-+ * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
-+ * Arnt Gulbrandsen.
-+ */
-+static inline unsigned short ip_fast_csum(unsigned char * iph,
-+ unsigned int ihl)
-+{
-+ unsigned int sum;
-+
-+ __asm__ __volatile__(
-+ "movl (%1), %0 ;\n"
-+ "subl $4, %2 ;\n"
-+ "jbe 2f ;\n"
-+ "addl 4(%1), %0 ;\n"
-+ "adcl 8(%1), %0 ;\n"
-+ "adcl 12(%1), %0 ;\n"
-+"1: adcl 16(%1), %0 ;\n"
-+ "lea 4(%1), %1 ;\n"
-+ "decl %2 ;\n"
-+ "jne 1b ;\n"
-+ "adcl $0, %0 ;\n"
-+ "movl %0, %2 ;\n"
-+ "shrl $16, %0 ;\n"
-+ "addw %w2, %w0 ;\n"
-+ "adcl $0, %0 ;\n"
-+ "notl %0 ;\n"
-+"2: ;\n"
-+ /* Since the input registers which are loaded with iph and ipl
-+ are modified, we must also specify them as outputs, or gcc
-+ will assume they contain their original values. */
-+ : "=r" (sum), "=r" (iph), "=r" (ihl)
-+ : "1" (iph), "2" (ihl));
-+ return(sum);
-+}
-+
-+/*
-+ * Fold a partial checksum
-+ */
-+
-+static inline unsigned int csum_fold(unsigned int sum)
-+{
-+ __asm__(
-+ "addl %1, %0 ;\n"
-+ "adcl $0xffff, %0 ;\n"
-+ : "=r" (sum)
-+ : "r" (sum << 16), "0" (sum & 0xffff0000)
-+ );
-+ return (~sum) >> 16;
-+}
-+
-+static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
-+ unsigned long daddr,
-+ unsigned short len,
-+ unsigned short proto,
-+ unsigned int sum)
-+{
-+ __asm__(
-+ "addl %1, %0 ;\n"
-+ "adcl %2, %0 ;\n"
-+ "adcl %3, %0 ;\n"
-+ "adcl $0, %0 ;\n"
-+ : "=r" (sum)
-+ : "g" (daddr), "g"(saddr), "g"((ntohs(len)<<16)+proto*256), "0"(sum));
-+ return sum;
-+}
-+
-+/*
-+ * computes the checksum of the TCP/UDP pseudo-header
-+ * returns a 16-bit checksum, already complemented
-+ */
-+static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
-+ unsigned long daddr,
-+ unsigned short len,
-+ unsigned short proto,
-+ unsigned int sum)
-+{
-+ return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
-+}
-+
-+/*
-+ * this routine is used for miscellaneous IP-like checksums, mainly
-+ * in icmp.c
-+ */
-+
-+static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
-+{
-+ return csum_fold (csum_partial(buff, len, 0));
-+}
-+
-+#define _HAVE_ARCH_IPV6_CSUM
-+static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
-+ struct in6_addr *daddr,
-+ __u32 len,
-+ unsigned short proto,
-+ unsigned int sum)
-+{
-+ __asm__(
-+ "addl 0(%1), %0 ;\n"
-+ "adcl 4(%1), %0 ;\n"
-+ "adcl 8(%1), %0 ;\n"
-+ "adcl 12(%1), %0 ;\n"
-+ "adcl 0(%2), %0 ;\n"
-+ "adcl 4(%2), %0 ;\n"
-+ "adcl 8(%2), %0 ;\n"
-+ "adcl 12(%2), %0 ;\n"
-+ "adcl %3, %0 ;\n"
-+ "adcl %4, %0 ;\n"
-+ "adcl $0, %0 ;\n"
-+ : "=&r" (sum)
-+ : "r" (saddr), "r" (daddr),
-+ "r"(htonl(len)), "r"(htonl(proto)), "0"(sum));
-+
-+ return csum_fold(sum);
-+}
-+
-+/*
-+ * Copy and checksum to user
-+ */
-+#define HAVE_CSUM_COPY_USER
-+static __inline__ unsigned int csum_and_copy_to_user(const char *src,
-+ char *dst, int len,
-+ int sum, int *err_ptr)
-+{
-+ if (access_ok(VERIFY_WRITE, dst, len))
-+ return(csum_partial_copy_to(src, dst, len, sum, err_ptr));
-+
-+ if (len)
-+ *err_ptr = -EFAULT;
-+
-+ return -1; /* invalid checksum */
-+}
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/frame.h um/arch/um/include/sysdep-i386/frame.h
---- orig/arch/um/include/sysdep-i386/frame.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/sysdep-i386/frame.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,29 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __FRAME_I386_H
-+#define __FRAME_I386_H
-+
-+struct arch_frame_data_raw {
-+ unsigned long fp_start;
-+ unsigned long sr;
-+};
-+
-+struct arch_frame_data {
-+ int fpstate_size;
-+};
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/frame_kern.h um/arch/um/include/sysdep-i386/frame_kern.h
---- orig/arch/um/include/sysdep-i386/frame_kern.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/sysdep-i386/frame_kern.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,69 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __FRAME_KERN_I386_H
-+#define __FRAME_KERN_I386_H
-+
-+/* This is called from sys_sigreturn. It takes the sp at the point of the
-+ * sigreturn system call and returns the address of the sigcontext struct
-+ * on the stack.
-+ */
-+
-+static inline void *sp_to_sc(unsigned long sp)
-+{
-+ return((void *) sp);
-+}
-+
-+static inline void *sp_to_uc(unsigned long sp)
-+{
-+ unsigned long uc;
-+
-+ uc = sp + signal_frame_si.uc_index -
-+ signal_frame_si.common.sp_index - 4;
-+ return((void *) uc);
-+}
-+
-+static inline void *sp_to_rt_sc(unsigned long sp)
-+{
-+ unsigned long sc;
-+
-+ sc = sp - signal_frame_si.common.sp_index +
-+ signal_frame_si.common.len - 4;
-+ return((void *) sc);
-+}
-+
-+static inline void *sp_to_mask(unsigned long sp)
-+{
-+ unsigned long mask;
-+
-+ mask = sp - signal_frame_sc.common.sp_index +
-+ signal_frame_sc.common.len - 8;
-+ return((void *) mask);
-+}
-+
-+extern int sc_size(void *data);
-+
-+static inline void *sp_to_rt_mask(unsigned long sp)
-+{
-+ unsigned long mask;
-+
-+ mask = sp - signal_frame_si.common.sp_index +
-+ signal_frame_si.common.len +
-+ sc_size(&signal_frame_si.common.arch) - 4;
-+ return((void *) mask);
-+}
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/frame_user.h um/arch/um/include/sysdep-i386/frame_user.h
---- orig/arch/um/include/sysdep-i386/frame_user.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/sysdep-i386/frame_user.h 2004-01-14 03:54:47.000000000 -0500
-@@ -0,0 +1,91 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __FRAME_USER_I386_H
-+#define __FRAME_USER_I386_H
-+
-+#include <asm/page.h>
-+#include "sysdep/frame.h"
-+
-+/* This stuff is to calculate the size of the fp state struct at runtime
-+ * because it has changed between 2.2 and 2.4 and it would be good for a
-+ * UML compiled on one to work on the other.
-+ * So, setup_arch_frame_raw fills in the arch struct with the raw data, which
-+ * just contains the address of the end of the sigcontext. This is invoked
-+ * from the signal handler.
-+ * setup_arch_frame uses that data to figure out what
-+ * arch_frame_data.fpstate_size should be. It really has no idea, since it's
-+ * not allowed to do sizeof(struct fpstate) but it's safe to consider that it's
-+ * everything from the end of the sigcontext up to the top of the stack. So,
-+ * it masks off the page number to get the offset within the page and subtracts
-+ * that from the page size, and that's how big the fpstate struct will be
-+ * considered to be.
-+ */
-+
-+static inline void setup_arch_frame_raw(struct arch_frame_data_raw *data,
-+ void *end, unsigned long srp)
-+{
-+ unsigned long sr = *((unsigned long *) srp);
-+
-+ data->fp_start = (unsigned long) end;
-+ if((sr & PAGE_MASK) == ((unsigned long) end & PAGE_MASK))
-+ data->sr = sr;
-+ else data->sr = 0;
-+}
-+
-+static inline void setup_arch_frame(struct arch_frame_data_raw *in,
-+ struct arch_frame_data *out)
-+{
-+ unsigned long fpstate_start = in->fp_start;
-+
-+ if(in->sr == 0){
-+ fpstate_start &= ~PAGE_MASK;
-+ out->fpstate_size = PAGE_SIZE - fpstate_start;
-+ }
-+ else {
-+ out->fpstate_size = in->sr - fpstate_start;
-+ }
-+}
-+
-+/* This figures out where on the stack the SA_RESTORER function address
-+ * is stored. For i386, it's the signal handler return address, so it's
-+ * located next to the frame pointer.
-+ * This is inlined, so __builtin_frame_address(0) is correct. Otherwise,
-+ * it would have to be __builtin_frame_address(1).
-+ */
-+
-+#define frame_restorer() \
-+({ \
-+ unsigned long *fp; \
-+\
-+ fp = __builtin_frame_address(0); \
-+ ((unsigned long) (fp + 1)); \
-+})
-+
-+/* Similarly, this returns the value of sp when the handler was first
-+ * entered. This is used to calculate the proper sp when delivering
-+ * signals.
-+ */
-+
-+#define frame_sp() \
-+({ \
-+ unsigned long *fp; \
-+\
-+ fp = __builtin_frame_address(0); \
-+ ((unsigned long) (fp + 1)); \
-+})
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/ptrace.h um/arch/um/include/sysdep-i386/ptrace.h
---- orig/arch/um/include/sysdep-i386/ptrace.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/sysdep-i386/ptrace.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,193 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __SYSDEP_I386_PTRACE_H
-+#define __SYSDEP_I386_PTRACE_H
-+
-+#include "uml-config.h"
-+
-+#ifdef UML_CONFIG_MODE_TT
-+#include "ptrace-tt.h"
-+#endif
-+
-+#ifdef UML_CONFIG_MODE_SKAS
-+#include "ptrace-skas.h"
-+#endif
-+
-+#include "choose-mode.h"
-+
-+union uml_pt_regs {
-+#ifdef UML_CONFIG_MODE_TT
-+ struct tt_regs {
-+ long syscall;
-+ void *sc;
-+ } tt;
-+#endif
-+#ifdef UML_CONFIG_MODE_SKAS
-+ struct skas_regs {
-+ unsigned long regs[HOST_FRAME_SIZE];
-+ unsigned long fp[HOST_FP_SIZE];
-+ unsigned long xfp[HOST_XFP_SIZE];
-+ unsigned long fault_addr;
-+ unsigned long fault_type;
-+ unsigned long trap_type;
-+ long syscall;
-+ int is_user;
-+ } skas;
-+#endif
-+};
-+
-+#define EMPTY_UML_PT_REGS { }
-+
-+extern int mode_tt;
-+
-+#define UPT_SC(r) ((r)->tt.sc)
-+#define UPT_IP(r) \
-+ CHOOSE_MODE(SC_IP(UPT_SC(r)), REGS_IP((r)->skas.regs))
-+#define UPT_SP(r) \
-+ CHOOSE_MODE(SC_SP(UPT_SC(r)), REGS_SP((r)->skas.regs))
-+#define UPT_EFLAGS(r) \
-+ CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs))
-+#define UPT_EAX(r) \
-+ CHOOSE_MODE(SC_EAX(UPT_SC(r)), REGS_EAX((r)->skas.regs))
-+#define UPT_EBX(r) \
-+ CHOOSE_MODE(SC_EBX(UPT_SC(r)), REGS_EBX((r)->skas.regs))
-+#define UPT_ECX(r) \
-+ CHOOSE_MODE(SC_ECX(UPT_SC(r)), REGS_ECX((r)->skas.regs))
-+#define UPT_EDX(r) \
-+ CHOOSE_MODE(SC_EDX(UPT_SC(r)), REGS_EDX((r)->skas.regs))
-+#define UPT_ESI(r) \
-+ CHOOSE_MODE(SC_ESI(UPT_SC(r)), REGS_ESI((r)->skas.regs))
-+#define UPT_EDI(r) \
-+ CHOOSE_MODE(SC_EDI(UPT_SC(r)), REGS_EDI((r)->skas.regs))
-+#define UPT_EBP(r) \
-+ CHOOSE_MODE(SC_EBP(UPT_SC(r)), REGS_EBP((r)->skas.regs))
-+#define UPT_ORIG_EAX(r) \
-+ CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall)
-+#define UPT_CS(r) \
-+ CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs))
-+#define UPT_SS(r) \
-+ CHOOSE_MODE(SC_SS(UPT_SC(r)), REGS_SS((r)->skas.regs))
-+#define UPT_DS(r) \
-+ CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs))
-+#define UPT_ES(r) \
-+ CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs))
-+#define UPT_FS(r) \
-+ CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs))
-+#define UPT_GS(r) \
-+ CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs))
-+
-+#define UPT_SYSCALL_ARG1(r) UPT_EBX(r)
-+#define UPT_SYSCALL_ARG2(r) UPT_ECX(r)
-+#define UPT_SYSCALL_ARG3(r) UPT_EDX(r)
-+#define UPT_SYSCALL_ARG4(r) UPT_ESI(r)
-+#define UPT_SYSCALL_ARG5(r) UPT_EDI(r)
-+#define UPT_SYSCALL_ARG6(r) UPT_EBP(r)
-+
-+extern int user_context(unsigned long sp);
-+
-+#define UPT_IS_USER(r) \
-+ CHOOSE_MODE(user_context(UPT_SP(r)), (r)->skas.is_user)
-+
-+struct syscall_args {
-+ unsigned long args[6];
-+};
-+
-+#define SYSCALL_ARGS(r) ((struct syscall_args) \
-+ { .args = { UPT_SYSCALL_ARG1(r), \
-+ UPT_SYSCALL_ARG2(r), \
-+ UPT_SYSCALL_ARG3(r), \
-+ UPT_SYSCALL_ARG4(r), \
-+ UPT_SYSCALL_ARG5(r), \
-+ UPT_SYSCALL_ARG6(r) } } )
-+
-+#define UPT_REG(regs, reg) \
-+ ({ unsigned long val; \
-+ switch(reg){ \
-+ case EIP: val = UPT_IP(regs); break; \
-+ case UESP: val = UPT_SP(regs); break; \
-+ case EAX: val = UPT_EAX(regs); break; \
-+ case EBX: val = UPT_EBX(regs); break; \
-+ case ECX: val = UPT_ECX(regs); break; \
-+ case EDX: val = UPT_EDX(regs); break; \
-+ case ESI: val = UPT_ESI(regs); break; \
-+ case EDI: val = UPT_EDI(regs); break; \
-+ case EBP: val = UPT_EBP(regs); break; \
-+ case ORIG_EAX: val = UPT_ORIG_EAX(regs); break; \
-+ case CS: val = UPT_CS(regs); break; \
-+ case SS: val = UPT_SS(regs); break; \
-+ case DS: val = UPT_DS(regs); break; \
-+ case ES: val = UPT_ES(regs); break; \
-+ case FS: val = UPT_FS(regs); break; \
-+ case GS: val = UPT_GS(regs); break; \
-+ case EFL: val = UPT_EFLAGS(regs); break; \
-+ default : \
-+ panic("Bad register in UPT_REG : %d\n", reg); \
-+ val = -1; \
-+ } \
-+ val; \
-+ })
-+
-+
-+#define UPT_SET(regs, reg, val) \
-+ do { \
-+ switch(reg){ \
-+ case EIP: UPT_IP(regs) = val; break; \
-+ case UESP: UPT_SP(regs) = val; break; \
-+ case EAX: UPT_EAX(regs) = val; break; \
-+ case EBX: UPT_EBX(regs) = val; break; \
-+ case ECX: UPT_ECX(regs) = val; break; \
-+ case EDX: UPT_EDX(regs) = val; break; \
-+ case ESI: UPT_ESI(regs) = val; break; \
-+ case EDI: UPT_EDI(regs) = val; break; \
-+ case EBP: UPT_EBP(regs) = val; break; \
-+ case ORIG_EAX: UPT_ORIG_EAX(regs) = val; break; \
-+ case CS: UPT_CS(regs) = val; break; \
-+ case SS: UPT_SS(regs) = val; break; \
-+ case DS: UPT_DS(regs) = val; break; \
-+ case ES: UPT_ES(regs) = val; break; \
-+ case FS: UPT_FS(regs) = val; break; \
-+ case GS: UPT_GS(regs) = val; break; \
-+ case EFL: UPT_EFLAGS(regs) = val; break; \
-+ default : \
-+ panic("Bad register in UPT_SET : %d\n", reg); \
-+ break; \
-+ } \
-+ } while (0)
-+
-+#define UPT_SET_SYSCALL_RETURN(r, res) \
-+ CHOOSE_MODE(SC_SET_SYSCALL_RETURN(UPT_SC(r), (res)), \
-+ REGS_SET_SYSCALL_RETURN((r)->skas.regs, (res)))
-+
-+#define UPT_RESTART_SYSCALL(r) \
-+ CHOOSE_MODE(SC_RESTART_SYSCALL(UPT_SC(r)), \
-+ REGS_RESTART_SYSCALL((r)->skas.regs))
-+
-+#define UPT_ORIG_SYSCALL(r) UPT_EAX(r)
-+#define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r)
-+#define UPT_SYSCALL_RET(r) UPT_EAX(r)
-+
-+#define UPT_SEGV_IS_FIXABLE(r) \
-+ CHOOSE_MODE(SC_SEGV_IS_FIXABLE(UPT_SC(r)), \
-+ REGS_SEGV_IS_FIXABLE(&r->skas))
-+
-+#define UPT_FAULT_ADDR(r) \
-+ CHOOSE_MODE(SC_FAULT_ADDR(UPT_SC(r)), REGS_FAULT_ADDR(&r->skas))
-+
-+#define UPT_FAULT_WRITE(r) \
-+ CHOOSE_MODE(SC_FAULT_WRITE(UPT_SC(r)), REGS_FAULT_WRITE(&r->skas))
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/ptrace_user.h um/arch/um/include/sysdep-i386/ptrace_user.h
---- orig/arch/um/include/sysdep-i386/ptrace_user.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/sysdep-i386/ptrace_user.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,62 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __SYSDEP_I386_PTRACE_USER_H__
-+#define __SYSDEP_I386_PTRACE_USER_H__
-+
-+#include <asm/ptrace.h>
-+
-+#define PT_OFFSET(r) ((r) * sizeof(long))
-+
-+#define PT_SYSCALL_NR(regs) ((regs)[ORIG_EAX])
-+#define PT_SYSCALL_NR_OFFSET PT_OFFSET(ORIG_EAX)
-+
-+#define PT_SYSCALL_ARG1_OFFSET PT_OFFSET(EBX)
-+#define PT_SYSCALL_ARG2_OFFSET PT_OFFSET(ECX)
-+#define PT_SYSCALL_ARG3_OFFSET PT_OFFSET(EDX)
-+#define PT_SYSCALL_ARG4_OFFSET PT_OFFSET(ESI)
-+#define PT_SYSCALL_ARG5_OFFSET PT_OFFSET(EDI)
-+
-+#define PT_SYSCALL_RET_OFFSET PT_OFFSET(EAX)
-+
-+#define PT_IP_OFFSET PT_OFFSET(EIP)
-+#define PT_IP(regs) ((regs)[EIP])
-+#define PT_SP(regs) ((regs)[UESP])
-+
-+#ifndef FRAME_SIZE
-+#define FRAME_SIZE (17)
-+#endif
-+#define FRAME_SIZE_OFFSET (FRAME_SIZE * sizeof(unsigned long))
-+
-+#define FP_FRAME_SIZE (27)
-+#define FPX_FRAME_SIZE (128)
-+
-+#ifdef PTRACE_GETREGS
-+#define UM_HAVE_GETREGS
-+#endif
-+
-+#ifdef PTRACE_SETREGS
-+#define UM_HAVE_SETREGS
-+#endif
-+
-+#ifdef PTRACE_GETFPREGS
-+#define UM_HAVE_GETFPREGS
-+#endif
-+
-+#ifdef PTRACE_SETFPREGS
-+#define UM_HAVE_SETFPREGS
-+#endif
-+
-+#ifdef PTRACE_GETFPXREGS
-+#define UM_HAVE_GETFPXREGS
-+#endif
-+
-+#ifdef PTRACE_SETFPXREGS
-+#define UM_HAVE_SETFPXREGS
-+#endif
-+
-+extern void update_debugregs(int seq);
-+
-+#endif
-diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/sigcontext.h um/arch/um/include/sysdep-i386/sigcontext.h
---- orig/arch/um/include/sysdep-i386/sigcontext.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/sysdep-i386/sigcontext.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,49 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __SYS_SIGCONTEXT_I386_H
-+#define __SYS_SIGCONTEXT_I386_H
-+
-+#include "sc.h"
-+
-+#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
-+
-+#define SC_RESTART_SYSCALL(sc) IP_RESTART_SYSCALL(SC_IP(sc))
-+#define SC_SET_SYSCALL_RETURN(sc, result) SC_EAX(sc) = (result)
-+
-+#define SC_FAULT_ADDR(sc) SC_CR2(sc)
-+#define SC_FAULT_TYPE(sc) SC_ERR(sc)
-+
-+#define FAULT_WRITE(err) (err & 2)
-+#define TO_SC_ERR(is_write) ((is_write) ? 2 : 0)
-+
-+#define SC_FAULT_WRITE(sc) (FAULT_WRITE(SC_ERR(sc)))
-+
-+#define SC_TRAP_TYPE(sc) SC_TRAPNO(sc)
-+
-+/* ptrace expects that, at the start of a system call, %eax contains
-+ * -ENOSYS, so this makes it so.
-+ */
-+#define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0)
-+
-+/* This is Page Fault */
-+#define SEGV_IS_FIXABLE(trap) (trap == 14)
-+
-+#define SC_SEGV_IS_FIXABLE(sc) (SEGV_IS_FIXABLE(SC_TRAPNO(sc)))
-+
-+extern unsigned long *sc_sigmask(void *sc_ptr);
-+extern int sc_get_fpregs(unsigned long buf, void *sc_ptr);
-+
-+#endif
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/syscalls.h um/arch/um/include/sysdep-i386/syscalls.h
---- orig/arch/um/include/sysdep-i386/syscalls.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/sysdep-i386/syscalls.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,61 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "asm/unistd.h"
-+#include "sysdep/ptrace.h"
-+
-+typedef long syscall_handler_t(struct pt_regs);
-+
-+#define EXECUTE_SYSCALL(syscall, regs) \
-+ ((long (*)(struct syscall_args)) (*sys_call_table[syscall]))(SYSCALL_ARGS(®s->regs))
-+
-+extern syscall_handler_t sys_modify_ldt;
-+extern syscall_handler_t old_mmap_i386;
-+extern syscall_handler_t old_select;
-+extern syscall_handler_t sys_ni_syscall;
-+
-+#define ARCH_SYSCALLS \
-+ [ __NR_mmap ] = old_mmap_i386, \
-+ [ __NR_select ] = old_select, \
-+ [ __NR_vm86old ] = sys_ni_syscall, \
-+ [ __NR_modify_ldt ] = sys_modify_ldt, \
-+ [ __NR_lchown32 ] = sys_lchown, \
-+ [ __NR_getuid32 ] = sys_getuid, \
-+ [ __NR_getgid32 ] = sys_getgid, \
-+ [ __NR_geteuid32 ] = sys_geteuid, \
-+ [ __NR_getegid32 ] = sys_getegid, \
-+ [ __NR_setreuid32 ] = sys_setreuid, \
-+ [ __NR_setregid32 ] = sys_setregid, \
-+ [ __NR_getgroups32 ] = sys_getgroups, \
-+ [ __NR_setgroups32 ] = sys_setgroups, \
-+ [ __NR_fchown32 ] = sys_fchown, \
-+ [ __NR_setresuid32 ] = sys_setresuid, \
-+ [ __NR_getresuid32 ] = sys_getresuid, \
-+ [ __NR_setresgid32 ] = sys_setresgid, \
-+ [ __NR_getresgid32 ] = sys_getresgid, \
-+ [ __NR_chown32 ] = sys_chown, \
-+ [ __NR_setuid32 ] = sys_setuid, \
-+ [ __NR_setgid32 ] = sys_setgid, \
-+ [ __NR_setfsuid32 ] = sys_setfsuid, \
-+ [ __NR_setfsgid32 ] = sys_setfsgid, \
-+ [ __NR_pivot_root ] = sys_pivot_root, \
-+ [ __NR_mincore ] = sys_mincore, \
-+ [ __NR_madvise ] = sys_madvise, \
-+ [ 222 ] = sys_ni_syscall,
-+
-+/* 222 doesn't yet have a name in include/asm-i386/unistd.h */
-+
-+#define LAST_ARCH_SYSCALL 222
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-ia64/ptrace.h um/arch/um/include/sysdep-ia64/ptrace.h
---- orig/arch/um/include/sysdep-ia64/ptrace.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/sysdep-ia64/ptrace.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,26 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __SYSDEP_IA64_PTRACE_H
-+#define __SYSDEP_IA64_PTRACE_H
-+
-+struct sys_pt_regs {
-+ int foo;
-+};
-+
-+#define EMPTY_REGS { 0 }
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-ia64/sigcontext.h um/arch/um/include/sysdep-ia64/sigcontext.h
---- orig/arch/um/include/sysdep-ia64/sigcontext.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/sysdep-ia64/sigcontext.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,20 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __SYSDEP_IA64_SIGCONTEXT_H
-+#define __SYSDEP_IA64_SIGCONTEXT_H
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-ia64/syscalls.h um/arch/um/include/sysdep-ia64/syscalls.h
---- orig/arch/um/include/sysdep-ia64/syscalls.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/sysdep-ia64/syscalls.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,20 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __SYSDEP_IA64_SYSCALLS_H
-+#define __SYSDEP_IA64_SYSCALLS_H
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-ppc/ptrace.h um/arch/um/include/sysdep-ppc/ptrace.h
---- orig/arch/um/include/sysdep-ppc/ptrace.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/sysdep-ppc/ptrace.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,104 @@
-+/*
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __SYS_PTRACE_PPC_H
-+#define __SYS_PTRACE_PPC_H
-+
-+#include "linux/config.h"
-+#include "linux/types.h"
-+
-+/* the following taken from <asm-ppc/ptrace.h> */
-+
-+#ifdef CONFIG_PPC64
-+#define PPC_REG unsigned long /*long*/
-+#else
-+#define PPC_REG unsigned long
-+#endif
-+struct sys_pt_regs_s {
-+ PPC_REG gpr[32];
-+ PPC_REG nip;
-+ PPC_REG msr;
-+ PPC_REG orig_gpr3; /* Used for restarting system calls */
-+ PPC_REG ctr;
-+ PPC_REG link;
-+ PPC_REG xer;
-+ PPC_REG ccr;
-+ PPC_REG mq; /* 601 only (not used at present) */
-+ /* Used on APUS to hold IPL value. */
-+ PPC_REG trap; /* Reason for being here */
-+ PPC_REG dar; /* Fault registers */
-+ PPC_REG dsisr;
-+ PPC_REG result; /* Result of a system call */
-+};
-+
-+#define NUM_REGS (sizeof(struct sys_pt_regs_s) / sizeof(PPC_REG))
-+
-+struct sys_pt_regs {
-+ PPC_REG regs[sizeof(struct sys_pt_regs_s) / sizeof(PPC_REG)];
-+};
-+
-+#define UM_MAX_REG (PT_FPR0)
-+#define UM_MAX_REG_OFFSET (UM_MAX_REG * sizeof(PPC_REG))
-+
-+#define EMPTY_REGS { { [ 0 ... NUM_REGS - 1] = 0 } }
-+
-+#define UM_REG(r, n) ((r)->regs[n])
-+
-+#define UM_SYSCALL_RET(r) UM_REG(r, PT_R3)
-+#define UM_SP(r) UM_REG(r, PT_R1)
-+#define UM_IP(r) UM_REG(r, PT_NIP)
-+#define UM_ELF_ZERO(r) UM_REG(r, PT_FPSCR)
-+#define UM_SYSCALL_NR(r) UM_REG(r, PT_R0)
-+#define UM_SYSCALL_ARG1(r) UM_REG(r, PT_ORIG_R3)
-+#define UM_SYSCALL_ARG2(r) UM_REG(r, PT_R4)
-+#define UM_SYSCALL_ARG3(r) UM_REG(r, PT_R5)
-+#define UM_SYSCALL_ARG4(r) UM_REG(r, PT_R6)
-+#define UM_SYSCALL_ARG5(r) UM_REG(r, PT_R7)
-+#define UM_SYSCALL_ARG6(r) UM_REG(r, PT_R8)
-+
-+#define UM_SYSCALL_NR_OFFSET (PT_R0 * sizeof(PPC_REG))
-+#define UM_SYSCALL_RET_OFFSET (PT_R3 * sizeof(PPC_REG))
-+#define UM_SYSCALL_ARG1_OFFSET (PT_R3 * sizeof(PPC_REG))
-+#define UM_SYSCALL_ARG2_OFFSET (PT_R4 * sizeof(PPC_REG))
-+#define UM_SYSCALL_ARG3_OFFSET (PT_R5 * sizeof(PPC_REG))
-+#define UM_SYSCALL_ARG4_OFFSET (PT_R6 * sizeof(PPC_REG))
-+#define UM_SYSCALL_ARG5_OFFSET (PT_R7 * sizeof(PPC_REG))
-+#define UM_SYSCALL_ARG6_OFFSET (PT_R8 * sizeof(PPC_REG))
-+#define UM_SP_OFFSET (PT_R1 * sizeof(PPC_REG))
-+#define UM_IP_OFFSET (PT_NIP * sizeof(PPC_REG))
-+#define UM_ELF_ZERO_OFFSET (PT_R3 * sizeof(PPC_REG))
-+
-+#define UM_SET_SYSCALL_RETURN(_regs, result) \
-+do { \
-+ if (result < 0) { \
-+ (_regs)->regs[PT_CCR] |= 0x10000000; \
-+ UM_SYSCALL_RET((_regs)) = -result; \
-+ } else { \
-+ UM_SYSCALL_RET((_regs)) = result; \
-+ } \
-+} while(0)
-+
-+extern void shove_aux_table(unsigned long sp);
-+#define UM_FIX_EXEC_STACK(sp) shove_aux_table(sp);
-+
-+/* These aren't actually defined. The undefs are just to make sure
-+ * everyone's clear on the concept.
-+ */
-+#undef UML_HAVE_GETREGS
-+#undef UML_HAVE_GETFPREGS
-+#undef UML_HAVE_SETREGS
-+#undef UML_HAVE_SETFPREGS
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-ppc/sigcontext.h um/arch/um/include/sysdep-ppc/sigcontext.h
---- orig/arch/um/include/sysdep-ppc/sigcontext.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/sysdep-ppc/sigcontext.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,62 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __SYS_SIGCONTEXT_PPC_H
-+#define __SYS_SIGCONTEXT_PPC_H
-+
-+#define DSISR_WRITE 0x02000000
-+
-+#define SC_FAULT_ADDR(sc) ({ \
-+ struct sigcontext *_sc = (sc); \
-+ long retval = -1; \
-+ switch (_sc->regs->trap) { \
-+ case 0x300: \
-+ /* data exception */ \
-+ retval = _sc->regs->dar; \
-+ break; \
-+ case 0x400: \
-+ /* instruction exception */ \
-+ retval = _sc->regs->nip; \
-+ break; \
-+ default: \
-+ panic("SC_FAULT_ADDR: unhandled trap type\n"); \
-+ } \
-+ retval; \
-+ })
-+
-+#define SC_FAULT_WRITE(sc) ({ \
-+ struct sigcontext *_sc = (sc); \
-+ long retval = -1; \
-+ switch (_sc->regs->trap) { \
-+ case 0x300: \
-+ /* data exception */ \
-+ retval = !!(_sc->regs->dsisr & DSISR_WRITE); \
-+ break; \
-+ case 0x400: \
-+ /* instruction exception: not a write */ \
-+ retval = 0; \
-+ break; \
-+ default: \
-+ panic("SC_FAULT_ADDR: unhandled trap type\n"); \
-+ } \
-+ retval; \
-+ })
-+
-+#define SC_IP(sc) ((sc)->regs->nip)
-+#define SC_SP(sc) ((sc)->regs->gpr[1])
-+#define SEGV_IS_FIXABLE(sc) (1)
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-ppc/syscalls.h um/arch/um/include/sysdep-ppc/syscalls.h
---- orig/arch/um/include/sysdep-ppc/syscalls.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/sysdep-ppc/syscalls.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,50 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+typedef long syscall_handler_t(unsigned long arg1, unsigned long arg2,
-+ unsigned long arg3, unsigned long arg4,
-+ unsigned long arg5, unsigned long arg6);
-+
-+#define EXECUTE_SYSCALL(syscall, regs) \
-+ (*sys_call_table[syscall])(UM_SYSCALL_ARG1(®s), \
-+ UM_SYSCALL_ARG2(®s), \
-+ UM_SYSCALL_ARG3(®s), \
-+ UM_SYSCALL_ARG4(®s), \
-+ UM_SYSCALL_ARG5(®s), \
-+ UM_SYSCALL_ARG6(®s))
-+
-+extern syscall_handler_t sys_mincore;
-+extern syscall_handler_t sys_madvise;
-+
-+/* old_mmap needs the correct prototype since syscall_kern.c includes
-+ * this file.
-+ */
-+int old_mmap(unsigned long addr, unsigned long len,
-+ unsigned long prot, unsigned long flags,
-+ unsigned long fd, unsigned long offset);
-+
-+#define ARCH_SYSCALLS \
-+ [ __NR_modify_ldt ] = sys_ni_syscall, \
-+ [ __NR_pciconfig_read ] = sys_ni_syscall, \
-+ [ __NR_pciconfig_write ] = sys_ni_syscall, \
-+ [ __NR_pciconfig_iobase ] = sys_ni_syscall, \
-+ [ __NR_pivot_root ] = sys_ni_syscall, \
-+ [ __NR_multiplexer ] = sys_ni_syscall, \
-+ [ __NR_mmap ] = old_mmap, \
-+ [ __NR_madvise ] = sys_madvise, \
-+ [ __NR_mincore ] = sys_mincore,
-+
-+#define LAST_ARCH_SYSCALL __NR_mincore
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/sysrq.h um/arch/um/include/sysrq.h
---- orig/arch/um/include/sysrq.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/sysrq.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_SYSRQ_H
-+#define __UM_SYSRQ_H
-+
-+extern void show_trace(unsigned long *stack);
-+
-+#endif
-diff -Naur -X ../exclude-files orig/arch/um/include/tempfile.h um/arch/um/include/tempfile.h
---- orig/arch/um/include/tempfile.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/tempfile.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,21 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __TEMPFILE_H__
-+#define __TEMPFILE_H__
-+
-+extern int make_tempfile(const char *template, char **tempname, int do_unlink);
-+
-+#endif
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/time_user.h um/arch/um/include/time_user.h
---- orig/arch/um/include/time_user.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/time_user.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,17 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __TIME_USER_H__
-+#define __TIME_USER_H__
-+
-+extern void timer(void);
-+extern void switch_timers(int to_real);
-+extern void set_interval(int timer_type);
-+extern void idle_sleep(int secs);
-+extern void enable_timer(void);
-+extern unsigned long time_lock(void);
-+extern void time_unlock(unsigned long);
-+
-+#endif
-diff -Naur -X ../exclude-files orig/arch/um/include/tlb.h um/arch/um/include/tlb.h
---- orig/arch/um/include/tlb.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/tlb.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,23 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __TLB_H__
-+#define __TLB_H__
-+
-+extern void mprotect_kernel_vm(int w);
-+extern void force_flush_all(void);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/ubd_user.h um/arch/um/include/ubd_user.h
---- orig/arch/um/include/ubd_user.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/ubd_user.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,79 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Copyright (C) 2001 RidgeRun, Inc (glonnon@ridgerun.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UM_UBD_USER_H
-+#define __UM_UBD_USER_H
-+
-+#include "os.h"
-+
-+enum ubd_req { UBD_READ, UBD_WRITE, UBD_MMAP };
-+
-+struct io_thread_req {
-+ enum ubd_req op;
-+ int fds[2];
-+ unsigned long offsets[2];
-+ unsigned long long offset;
-+ unsigned long length;
-+ char *buffer;
-+ int sectorsize;
-+ unsigned long sector_mask;
-+ unsigned long long cow_offset;
-+ unsigned long bitmap_words[2];
-+ int map_fd;
-+ unsigned long long map_offset;
-+ int error;
-+};
-+
-+extern int open_ubd_file(char *file, struct openflags *openflags,
-+ char **backing_file_out, int *bitmap_offset_out,
-+ unsigned long *bitmap_len_out, int *data_offset_out,
-+ int *create_cow_out);
-+extern int create_cow_file(char *cow_file, char *backing_file,
-+ struct openflags flags, int sectorsize,
-+ int alignment, int *bitmap_offset_out,
-+ unsigned long *bitmap_len_out,
-+ int *data_offset_out);
-+extern int read_cow_bitmap(int fd, void *buf, int offset, int len);
-+extern int read_ubd_fs(int fd, void *buffer, int len);
-+extern int write_ubd_fs(int fd, char *buffer, int len);
-+extern int start_io_thread(unsigned long sp, int *fds_out);
-+extern void do_io(struct io_thread_req *req);
-+
-+static inline int ubd_test_bit(__u64 bit, unsigned char *data)
-+{
-+ __u64 n;
-+ int bits, off;
-+
-+ bits = sizeof(data[0]) * 8;
-+ n = bit / bits;
-+ off = bit % bits;
-+ return((data[n] & (1 << off)) != 0);
-+}
-+
-+static inline void ubd_set_bit(__u64 bit, unsigned char *data)
-+{
-+ __u64 n;
-+ int bits, off;
-+
-+ bits = sizeof(data[0]) * 8;
-+ n = bit / bits;
-+ off = bit % bits;
-+ data[n] |= (1 << off);
-+}
-+
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/umid.h um/arch/um/include/umid.h
---- orig/arch/um/include/umid.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/umid.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,22 @@
-+/*
-+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UMID_H__
-+#define __UMID_H__
-+
-+extern int umid_file_name(char *name, char *buf, int len);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/uml_uaccess.h um/arch/um/include/uml_uaccess.h
---- orig/arch/um/include/uml_uaccess.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/uml_uaccess.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,28 @@
-+/*
-+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UML_UACCESS_H__
-+#define __UML_UACCESS_H__
-+
-+extern int __do_copy_to_user(void *to, const void *from, int n,
-+ void **fault_addr, void **fault_catcher);
-+extern unsigned long __do_user_copy(void *to, const void *from, int n,
-+ void **fault_addr, void **fault_catcher,
-+ void (*op)(void *to, const void *from,
-+ int n), int *faulted_out);
-+void __do_copy(void *to, const void *from, int n);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/um_mmu.h um/arch/um/include/um_mmu.h
---- orig/arch/um/include/um_mmu.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/um_mmu.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,40 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __ARCH_UM_MMU_H
-+#define __ARCH_UM_MMU_H
-+
-+#include "linux/config.h"
-+#include "choose-mode.h"
-+
-+#ifdef CONFIG_MODE_TT
-+#include "../kernel/tt/include/mmu.h"
-+#endif
-+
-+#ifdef CONFIG_MODE_SKAS
-+#include "../kernel/skas/include/mmu.h"
-+#endif
-+
-+typedef union {
-+#ifdef CONFIG_MODE_TT
-+ struct mmu_context_tt tt;
-+#endif
-+#ifdef CONFIG_MODE_SKAS
-+ struct mmu_context_skas skas;
-+#endif
-+} mm_context_t;
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/umn.h um/arch/um/include/umn.h
---- orig/arch/um/include/umn.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/umn.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,27 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UMN_H
-+#define __UMN_H
-+
-+extern int open_umn_tty(int *slave_out, int *slipno_out);
-+extern void close_umn_tty(int master, int slave);
-+extern int umn_send_packet(int fd, void *data, int len);
-+extern int set_umn_addr(int fd, char *addr, char *ptp_addr);
-+extern void slip_unesc(unsigned char s);
-+extern void umn_read(int fd);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/um_uaccess.h um/arch/um/include/um_uaccess.h
---- orig/arch/um/include/um_uaccess.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/um_uaccess.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,124 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __ARCH_UM_UACCESS_H
-+#define __ARCH_UM_UACCESS_H
-+
-+#include "linux/config.h"
-+#include "choose-mode.h"
-+
-+#ifdef CONFIG_MODE_TT
-+#include "../kernel/tt/include/uaccess.h"
-+#endif
-+
-+#ifdef CONFIG_MODE_SKAS
-+#include "../kernel/skas/include/uaccess.h"
-+#endif
-+
-+#define access_ok(type, addr, size) \
-+ CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size)
-+
-+static inline int verify_area(int type, const void * addr, unsigned long size)
-+{
-+ return(CHOOSE_MODE_PROC(verify_area_tt, verify_area_skas, type, addr,
-+ size));
-+}
-+
-+static inline int copy_from_user(void *to, const void *from, int n)
-+{
-+ return(CHOOSE_MODE_PROC(copy_from_user_tt, copy_from_user_skas, to,
-+ from, n));
-+}
-+
-+static inline int copy_to_user(void *to, const void *from, int n)
-+{
-+ return(CHOOSE_MODE_PROC(copy_to_user_tt, copy_to_user_skas, to,
-+ from, n));
-+}
-+
-+/*
-+ * strncpy_from_user: - Copy a NUL terminated string from userspace.
-+ * @dst: Destination address, in kernel space. This buffer must be at
-+ * least @count bytes long.
-+ * @src: Source address, in user space.
-+ * @count: Maximum number of bytes to copy, including the trailing NUL.
-+ *
-+ * Copies a NUL-terminated string from userspace to kernel space.
-+ *
-+ * On success, returns the length of the string (not including the trailing
-+ * NUL).
-+ *
-+ * If access to userspace fails, returns -EFAULT (some data may have been
-+ * copied).
-+ *
-+ * If @count is smaller than the length of the string, copies @count bytes
-+ * and returns @count.
-+ */
-+
-+static inline int strncpy_from_user(char *dst, const char *src, int count)
-+{
-+ return(CHOOSE_MODE_PROC(strncpy_from_user_tt, strncpy_from_user_skas,
-+ dst, src, count));
-+}
-+
-+/*
-+ * __clear_user: - Zero a block of memory in user space, with less checking.
-+ * @to: Destination address, in user space.
-+ * @n: Number of bytes to zero.
-+ *
-+ * Zero a block of memory in user space. Caller must check
-+ * the specified block with access_ok() before calling this function.
-+ *
-+ * Returns number of bytes that could not be cleared.
-+ * On success, this will be zero.
-+ */
-+static inline int __clear_user(void *mem, int len)
-+{
-+ return(CHOOSE_MODE_PROC(__clear_user_tt, __clear_user_skas, mem, len));
-+}
-+
-+/*
-+ * clear_user: - Zero a block of memory in user space.
-+ * @to: Destination address, in user space.
-+ * @n: Number of bytes to zero.
-+ *
-+ * Zero a block of memory in user space.
-+ *
-+ * Returns number of bytes that could not be cleared.
-+ * On success, this will be zero.
-+ */
-+static inline int clear_user(void *mem, int len)
-+{
-+ return(CHOOSE_MODE_PROC(clear_user_tt, clear_user_skas, mem, len));
-+}
-+
-+/*
-+ * strlen_user: - Get the size of a string in user space.
-+ * @str: The string to measure.
-+ * @n: The maximum valid length
-+ *
-+ * Get the size of a NUL-terminated string in user space.
-+ *
-+ * Returns the size of the string INCLUDING the terminating NUL.
-+ * On exception, returns 0.
-+ * If the string is too long, returns a value greater than @n.
-+ */
-+static inline int strnlen_user(const void *str, int len)
-+{
-+ return(CHOOSE_MODE_PROC(strnlen_user_tt, strnlen_user_skas, str, len));
-+}
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/user.h um/arch/um/include/user.h
---- orig/arch/um/include/user.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/user.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,29 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __USER_H__
-+#define __USER_H__
-+
-+extern void panic(const char *fmt, ...);
-+extern int printk(const char *fmt, ...);
-+extern void schedule(void);
-+extern void *um_kmalloc(int size);
-+extern void *um_kmalloc_atomic(int size);
-+extern void kfree(void *ptr);
-+extern int in_aton(char *str);
-+extern int open_gdb_chan(void);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/include/user_util.h um/arch/um/include/user_util.h
---- orig/arch/um/include/user_util.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/include/user_util.h 2003-11-09 11:36:31.000000000 -0500
-@@ -0,0 +1,103 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __USER_UTIL_H__
-+#define __USER_UTIL_H__
-+
-+#include "sysdep/ptrace.h"
-+
-+extern int mode_tt;
-+
-+extern int grantpt(int __fd);
-+extern int unlockpt(int __fd);
-+extern char *ptsname(int __fd);
-+
-+struct cpu_task {
-+ int pid;
-+ void *task;
-+};
-+
-+extern struct cpu_task cpu_tasks[];
-+
-+struct signal_info {
-+ void (*handler)(int, union uml_pt_regs *);
-+ int is_irq;
-+};
-+
-+extern struct signal_info sig_info[];
-+
-+extern unsigned long low_physmem;
-+extern unsigned long high_physmem;
-+extern unsigned long uml_physmem;
-+extern unsigned long uml_reserved;
-+extern unsigned long end_vm;
-+extern unsigned long start_vm;
-+extern unsigned long highmem;
-+
-+extern char host_info[];
-+
-+extern char saved_command_line[];
-+extern char command_line[];
-+
-+extern char *tempdir;
-+
-+extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end;
-+extern unsigned long _unprotected_end;
-+extern unsigned long brk_start;
-+
-+extern int pty_output_sigio;
-+extern int pty_close_sigio;
-+
-+extern void stop(void);
-+extern void stack_protections(unsigned long address);
-+extern void task_protections(unsigned long address);
-+extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
-+extern void *add_signal_handler(int sig, void (*handler)(int));
-+extern int start_fork_tramp(void *arg, unsigned long temp_stack,
-+ int clone_flags, int (*tramp)(void *));
-+extern int linux_main(int argc, char **argv);
-+extern void set_cmdline(char *cmd);
-+extern void input_cb(void (*proc)(void *), void *arg, int arg_len);
-+extern int get_pty(void);
-+extern void *um_kmalloc(int size);
-+extern int raw(int fd, int complain);
-+extern int switcheroo(int fd, int prot, void *from, void *to, int size);
-+extern void setup_machinename(char *machine_out);
-+extern void setup_hostinfo(void);
-+extern void add_arg(char *cmd_line, char *arg);
-+extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int));
-+extern void init_new_thread_signals(int altstack);
-+extern void do_exec(int old_pid, int new_pid);
-+extern void tracer_panic(char *msg, ...);
-+extern char *get_umid(int only_if_set);
-+extern void do_longjmp(void *p, int val);
-+extern void suspend_new_thread(int fd);
-+extern int detach(int pid, int sig);
-+extern int attach(int pid);
-+extern void kill_child_dead(int pid);
-+extern int cont(int pid);
-+extern void check_ptrace(void);
-+extern void check_sigio(void);
-+extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr);
-+extern void write_sigio_workaround(void);
-+extern void arch_check_bugs(void);
-+extern int cpu_feature(char *what, char *buf, int len);
-+extern int arch_handle_signal(int sig, union uml_pt_regs *regs);
-+extern int arch_fixup(unsigned long address, void *sc_ptr);
-+extern int can_do_skas(void);
-+extern void arch_init_thread(void);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/checksum.c um/arch/um/kernel/checksum.c
---- orig/arch/um/kernel/checksum.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/checksum.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,42 @@
-+#include "asm/uaccess.h"
-+#include "linux/errno.h"
-+
-+extern unsigned int arch_csum_partial(const char *buff, int len, int sum);
-+
-+extern unsigned int csum_partial(char *buff, int len, int sum)
-+{
-+ return(arch_csum_partial(buff, len, sum));
-+}
-+
-+unsigned int csum_partial_copy_to(const char *src, char *dst, int len,
-+ int sum, int *err_ptr)
-+{
-+ if(copy_to_user(dst, src, len)){
-+ *err_ptr = -EFAULT;
-+ return(-1);
-+ }
-+
-+ return(arch_csum_partial(src, len, sum));
-+}
-+
-+unsigned int csum_partial_copy_from(const char *src, char *dst, int len,
-+ int sum, int *err_ptr)
-+{
-+ if(copy_from_user(dst, src, len)){
-+ *err_ptr = -EFAULT;
-+ return(-1);
-+ }
-+
-+ return(arch_csum_partial(dst, len, sum));
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/config.c.in um/arch/um/kernel/config.c.in
---- orig/arch/um/kernel/config.c.in 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/config.c.in 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,32 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include "init.h"
-+
-+static __initdata char *config = "CONFIG";
-+
-+static int __init print_config(char *line, int *add)
-+{
-+ printf("%s", config);
-+ exit(0);
-+}
-+
-+__uml_setup("--showconfig", print_config,
-+"--showconfig\n"
-+" Prints the config file that this UML binary was generated from.\n\n"
-+);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/exec_kern.c um/arch/um/kernel/exec_kern.c
---- orig/arch/um/kernel/exec_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/exec_kern.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,86 @@
-+/*
-+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/slab.h"
-+#include "linux/smp_lock.h"
-+#include "asm/ptrace.h"
-+#include "asm/pgtable.h"
-+#include "asm/pgalloc.h"
-+#include "asm/uaccess.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "mem_user.h"
-+#include "kern.h"
-+#include "irq_user.h"
-+#include "tlb.h"
-+#include "2_5compat.h"
-+#include "os.h"
-+#include "time_user.h"
-+#include "choose-mode.h"
-+#include "mode_kern.h"
-+
-+void flush_thread(void)
-+{
-+ CHOOSE_MODE(flush_thread_tt(), flush_thread_skas());
-+}
-+
-+void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
-+{
-+ CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp);
-+}
-+
-+extern void log_exec(char **argv, void *tty);
-+
-+static int execve1(char *file, char **argv, char **env)
-+{
-+ int error;
-+
-+#ifdef CONFIG_TTY_LOG
-+ log_exec(argv, current->tty);
-+#endif
-+ error = do_execve(file, argv, env, ¤t->thread.regs);
-+ if (error == 0){
-+ current->ptrace &= ~PT_DTRACE;
-+ set_cmdline(current_cmd());
-+ }
-+ return(error);
-+}
-+
-+int um_execve(char *file, char **argv, char **env)
-+{
-+ int err;
-+
-+ err = execve1(file, argv, env);
-+ if(!err)
-+ do_longjmp(current->thread.exec_buf, 1);
-+ return(err);
-+}
-+
-+int sys_execve(char *file, char **argv, char **env)
-+{
-+ int error;
-+ char *filename;
-+
-+ lock_kernel();
-+ filename = getname((char *) file);
-+ error = PTR_ERR(filename);
-+ if (IS_ERR(filename)) goto out;
-+ error = execve1(filename, argv, env);
-+ putname(filename);
-+ out:
-+ unlock_kernel();
-+ return(error);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/exitcode.c um/arch/um/kernel/exitcode.c
---- orig/arch/um/kernel/exitcode.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/exitcode.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,73 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/init.h"
-+#include "linux/ctype.h"
-+#include "linux/proc_fs.h"
-+#include "asm/uaccess.h"
-+
-+/* If read and write race, the read will still atomically read a valid
-+ * value.
-+ */
-+int uml_exitcode = 0;
-+
-+static int read_proc_exitcode(char *page, char **start, off_t off,
-+ int count, int *eof, void *data)
-+{
-+ int len;
-+
-+ len = sprintf(page, "%d\n", uml_exitcode);
-+ len -= off;
-+ if(len <= off+count) *eof = 1;
-+ *start = page + off;
-+ if(len > count) len = count;
-+ if(len < 0) len = 0;
-+ return(len);
-+}
-+
-+static int write_proc_exitcode(struct file *file, const char *buffer,
-+ unsigned long count, void *data)
-+{
-+ char *end, buf[sizeof("nnnnn\0")];
-+ int tmp;
-+
-+ if(copy_from_user(buf, buffer, count))
-+ return(-EFAULT);
-+ tmp = simple_strtol(buf, &end, 0);
-+ if((*end != '\0') && !isspace(*end))
-+ return(-EINVAL);
-+ uml_exitcode = tmp;
-+ return(count);
-+}
-+
-+static int make_proc_exitcode(void)
-+{
-+ struct proc_dir_entry *ent;
-+
-+ ent = create_proc_entry("exitcode", 0600, &proc_root);
-+ if(ent == NULL){
-+ printk("make_proc_exitcode : Failed to register "
-+ "/proc/exitcode\n");
-+ return(0);
-+ }
-+
-+ ent->read_proc = read_proc_exitcode;
-+ ent->write_proc = write_proc_exitcode;
-+
-+ return(0);
-+}
-+
-+__initcall(make_proc_exitcode);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/frame.c um/arch/um/kernel/frame.c
---- orig/arch/um/kernel/frame.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/frame.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,341 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <string.h>
-+#include <signal.h>
-+#include <wait.h>
-+#include <sched.h>
-+#include <errno.h>
-+#include <sys/ptrace.h>
-+#include <sys/syscall.h>
-+#include <sys/mman.h>
-+#include <asm/page.h>
-+#include <asm/ptrace.h>
-+#include <asm/sigcontext.h>
-+#include "sysdep/ptrace.h"
-+#include "sysdep/sigcontext.h"
-+#include "frame_user.h"
-+#include "kern_util.h"
-+#include "ptrace_user.h"
-+#include "os.h"
-+
-+static int capture_stack(int (*child)(void *arg), void *arg, void *sp,
-+ unsigned long top, void **data_out)
-+{
-+ unsigned long regs[FRAME_SIZE];
-+ int pid, status, n, len;
-+
-+ /* Start the child as a thread */
-+ pid = clone(child, sp, CLONE_VM | SIGCHLD, arg);
-+ if(pid < 0){
-+ printf("capture_stack : clone failed - errno = %d\n", errno);
-+ exit(1);
-+ }
-+
-+ /* Wait for it to stop itself and continue it with a SIGUSR1 to force
-+ * it into the signal handler.
-+ */
-+ n = waitpid(pid, &status, WUNTRACED);
-+ if(n < 0){
-+ printf("capture_stack : waitpid failed - errno = %d\n", errno);
-+ exit(1);
-+ }
-+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)){
-+ fprintf(stderr, "capture_stack : Expected SIGSTOP, "
-+ "got status = 0x%x\n", status);
-+ exit(1);
-+ }
-+ if(ptrace(PTRACE_CONT, pid, 0, SIGUSR1) < 0){
-+ printf("capture_stack : PTRACE_CONT failed - errno = %d\n",
-+ errno);
-+ exit(1);
-+ }
-+
-+ /* Wait for it to stop itself again and grab its registers again.
-+ * At this point, the handler has stuffed the addresses of
-+ * sig, sc, and SA_RESTORER in raw.
-+ */
-+ n = waitpid(pid, &status, WUNTRACED);
-+ if(n < 0){
-+ printf("capture_stack : waitpid failed - errno = %d\n", errno);
-+ exit(1);
-+ }
-+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)){
-+ fprintf(stderr, "capture_stack : Expected SIGSTOP, "
-+ "got status = 0x%x\n", status);
-+ exit(1);
-+ }
-+ if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0){
-+ printf("capture_stack : PTRACE_GETREGS failed - errno = %d\n",
-+ errno);
-+ exit(1);
-+ }
-+
-+ /* It has outlived its usefulness, so continue it so it can exit */
-+ if(ptrace(PTRACE_CONT, pid, 0, 0) < 0){
-+ printf("capture_stack : PTRACE_CONT failed - errno = %d\n",
-+ errno);
-+ exit(1);
-+ }
-+ if(waitpid(pid, &status, 0) < 0){
-+ printf("capture_stack : waitpid failed - errno = %d\n", errno);
-+ exit(1);
-+ }
-+ if(!WIFSIGNALED(status) || (WTERMSIG(status) != 9)){
-+ printf("capture_stack : Expected exit signal 9, "
-+ "got status = 0x%x\n", status);
-+ exit(1);
-+ }
-+
-+ /* The frame that we want is the top of the signal stack */
-+
-+ len = top - PT_SP(regs);
-+ *data_out = malloc(len);
-+ if(*data_out == NULL){
-+ printf("capture_stack : malloc failed - errno = %d\n", errno);
-+ exit(1);
-+ }
-+ memcpy(*data_out, (void *) PT_SP(regs), len);
-+
-+ return(len);
-+}
-+
-+struct common_raw {
-+ void *stack;
-+ int size;
-+ unsigned long sig;
-+ unsigned long sr;
-+ unsigned long sp;
-+ struct arch_frame_data_raw arch;
-+};
-+
-+#define SA_RESTORER (0x04000000)
-+
-+typedef unsigned long old_sigset_t;
-+
-+struct old_sigaction {
-+ __sighandler_t handler;
-+ old_sigset_t sa_mask;
-+ unsigned long sa_flags;
-+ void (*sa_restorer)(void);
-+};
-+
-+static void child_common(struct common_raw *common, sighandler_t handler,
-+ int restorer, int flags)
-+{
-+ stack_t ss = ((stack_t) { .ss_sp = common->stack,
-+ .ss_flags = 0,
-+ .ss_size = common->size });
-+ int err;
-+
-+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){
-+ printf("PTRACE_TRACEME failed, errno = %d\n", errno);
-+ }
-+ if(sigaltstack(&ss, NULL) < 0){
-+ printf("sigaltstack failed - errno = %d\n", errno);
-+ kill(getpid(), SIGKILL);
-+ }
-+
-+ if(restorer){
-+ struct sigaction sa;
-+
-+ sa.sa_handler = handler;
-+ sigemptyset(&sa.sa_mask);
-+ sa.sa_flags = SA_ONSTACK | flags;
-+ err = sigaction(SIGUSR1, &sa, NULL);
-+ }
-+ else {
-+ struct old_sigaction sa;
-+
-+ sa.handler = handler;
-+ sa.sa_mask = 0;
-+ sa.sa_flags = (SA_ONSTACK | flags) & ~SA_RESTORER;
-+ err = syscall(__NR_sigaction, SIGUSR1, &sa, NULL);
-+ }
-+
-+ if(err < 0){
-+ printf("sigaction failed - errno = %d\n", errno);
-+ kill(getpid(), SIGKILL);
-+ }
-+
-+ os_stop_process(os_getpid());
-+}
-+
-+/* Changed only during early boot */
-+struct sc_frame signal_frame_sc;
-+
-+struct sc_frame signal_frame_sc_sr;
-+
-+struct sc_frame_raw {
-+ struct common_raw common;
-+ unsigned long sc;
-+ int restorer;
-+};
-+
-+/* Changed only during early boot */
-+static struct sc_frame_raw *raw_sc = NULL;
-+
-+static void sc_handler(int sig, struct sigcontext sc)
-+{
-+ raw_sc->common.sig = (unsigned long) &sig;
-+ raw_sc->common.sr = frame_restorer();
-+ raw_sc->common.sp = frame_sp();
-+ raw_sc->sc = (unsigned long) ≻
-+ setup_arch_frame_raw(&raw_sc->common.arch, &sc + 1, raw_sc->common.sr);
-+
-+ os_stop_process(os_getpid());
-+ kill(getpid(), SIGKILL);
-+}
-+
-+static int sc_child(void *arg)
-+{
-+ raw_sc = arg;
-+ child_common(&raw_sc->common, (sighandler_t) sc_handler,
-+ raw_sc->restorer, 0);
-+ return(-1);
-+}
-+
-+/* Changed only during early boot */
-+struct si_frame signal_frame_si;
-+
-+struct si_frame_raw {
-+ struct common_raw common;
-+ unsigned long sip;
-+ unsigned long si;
-+ unsigned long ucp;
-+ unsigned long uc;
-+};
-+
-+/* Changed only during early boot */
-+static struct si_frame_raw *raw_si = NULL;
-+
-+static void si_handler(int sig, siginfo_t *si, struct ucontext *ucontext)
-+{
-+ raw_si->common.sig = (unsigned long) &sig;
-+ raw_si->common.sr = frame_restorer();
-+ raw_si->common.sp = frame_sp();
-+ raw_si->sip = (unsigned long) &si;
-+ raw_si->si = (unsigned long) si;
-+ raw_si->ucp = (unsigned long) &ucontext;
-+ raw_si->uc = (unsigned long) ucontext;
-+ setup_arch_frame_raw(&raw_si->common.arch,
-+ ucontext->uc_mcontext.fpregs, raw_si->common.sr);
-+
-+ os_stop_process(os_getpid());
-+ kill(getpid(), SIGKILL);
-+}
-+
-+static int si_child(void *arg)
-+{
-+ raw_si = arg;
-+ child_common(&raw_si->common, (sighandler_t) si_handler, 1,
-+ SA_SIGINFO);
-+ return(-1);
-+}
-+
-+static int relative_sr(unsigned long sr, int sr_index, void *stack,
-+ void *framep)
-+{
-+ unsigned long *srp = (unsigned long *) sr;
-+ unsigned long frame = (unsigned long) framep;
-+
-+ if((*srp & PAGE_MASK) == (unsigned long) stack){
-+ *srp -= sr;
-+ *((unsigned long *) (frame + sr_index)) = *srp;
-+ return(1);
-+ }
-+ else return(0);
-+}
-+
-+static unsigned long capture_stack_common(int (*proc)(void *), void *arg,
-+ struct common_raw *common_in,
-+ void *top, void *sigstack,
-+ int stack_len,
-+ struct frame_common *common_out)
-+{
-+ unsigned long sig_top = (unsigned long) sigstack + stack_len, base;
-+
-+ common_in->stack = (void *) sigstack;
-+ common_in->size = stack_len;
-+ common_out->len = capture_stack(proc, arg, top, sig_top,
-+ &common_out->data);
-+ base = sig_top - common_out->len;
-+ common_out->sig_index = common_in->sig - base;
-+ common_out->sp_index = common_in->sp - base;
-+ common_out->sr_index = common_in->sr - base;
-+ common_out->sr_relative = relative_sr(common_in->sr,
-+ common_out->sr_index, sigstack,
-+ common_out->data);
-+ return(base);
-+}
-+
-+void capture_signal_stack(void)
-+{
-+ struct sc_frame_raw raw_sc;
-+ struct si_frame_raw raw_si;
-+ void *stack, *sigstack;
-+ unsigned long top, base;
-+
-+ stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
-+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-+ sigstack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
-+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-+ if((stack == MAP_FAILED) || (sigstack == MAP_FAILED)){
-+ printf("capture_signal_stack : mmap failed - errno = %d\n",
-+ errno);
-+ exit(1);
-+ }
-+
-+ top = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
-+
-+ /* Get the sigcontext, no sigrestorer layout */
-+ raw_sc.restorer = 0;
-+ base = capture_stack_common(sc_child, &raw_sc, &raw_sc.common,
-+ (void *) top, sigstack, PAGE_SIZE,
-+ &signal_frame_sc.common);
-+
-+ signal_frame_sc.sc_index = raw_sc.sc - base;
-+ setup_arch_frame(&raw_sc.common.arch, &signal_frame_sc.common.arch);
-+
-+ /* Ditto for the sigcontext, sigrestorer layout */
-+ raw_sc.restorer = 1;
-+ base = capture_stack_common(sc_child, &raw_sc, &raw_sc.common,
-+ (void *) top, sigstack, PAGE_SIZE,
-+ &signal_frame_sc_sr.common);
-+ signal_frame_sc_sr.sc_index = raw_sc.sc - base;
-+ setup_arch_frame(&raw_sc.common.arch, &signal_frame_sc_sr.common.arch);
-+
-+ /* And the siginfo layout */
-+
-+ base = capture_stack_common(si_child, &raw_si, &raw_si.common,
-+ (void *) top, sigstack, PAGE_SIZE,
-+ &signal_frame_si.common);
-+ signal_frame_si.sip_index = raw_si.sip - base;
-+ signal_frame_si.si_index = raw_si.si - base;
-+ signal_frame_si.ucp_index = raw_si.ucp - base;
-+ signal_frame_si.uc_index = raw_si.uc - base;
-+ setup_arch_frame(&raw_si.common.arch, &signal_frame_si.common.arch);
-+
-+ if((munmap(stack, PAGE_SIZE) < 0) ||
-+ (munmap(sigstack, PAGE_SIZE) < 0)){
-+ printf("capture_signal_stack : munmap failed - errno = %d\n",
-+ errno);
-+ exit(1);
-+ }
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/frame_kern.c um/arch/um/kernel/frame_kern.c
---- orig/arch/um/kernel/frame_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/frame_kern.c 2003-11-19 03:32:43.000000000 -0500
-@@ -0,0 +1,174 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "asm/ptrace.h"
-+#include "asm/uaccess.h"
-+#include "asm/signal.h"
-+#include "asm/uaccess.h"
-+#include "asm/ucontext.h"
-+#include "frame_kern.h"
-+#include "sigcontext.h"
-+#include "sysdep/ptrace.h"
-+#include "choose-mode.h"
-+#include "mode.h"
-+
-+int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
-+{
-+ if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
-+ return -EFAULT;
-+ if (from->si_code < 0)
-+ return __copy_to_user(to, from, sizeof(siginfo_t));
-+ else {
-+ int err;
-+
-+ /* If you change siginfo_t structure, please be sure
-+ this code is fixed accordingly.
-+ It should never copy any pad contained in the structure
-+ to avoid security leaks, but must copy the generic
-+ 3 ints plus the relevant union member. */
-+ err = __put_user(from->si_signo, &to->si_signo);
-+ err |= __put_user(from->si_errno, &to->si_errno);
-+ err |= __put_user((short)from->si_code, &to->si_code);
-+ /* First 32bits of unions are always present. */
-+ err |= __put_user(from->si_pid, &to->si_pid);
-+ switch (from->si_code >> 16) {
-+ case __SI_FAULT >> 16:
-+ break;
-+ case __SI_CHLD >> 16:
-+ err |= __put_user(from->si_utime, &to->si_utime);
-+ err |= __put_user(from->si_stime, &to->si_stime);
-+ err |= __put_user(from->si_status, &to->si_status);
-+ default:
-+ err |= __put_user(from->si_uid, &to->si_uid);
-+ break;
-+ }
-+ return err;
-+ }
-+}
-+
-+static int copy_restorer(void (*restorer)(void), unsigned long start,
-+ unsigned long sr_index, int sr_relative)
-+{
-+ unsigned long sr;
-+
-+ if(sr_relative){
-+ sr = (unsigned long) restorer;
-+ sr += start + sr_index;
-+ restorer = (void (*)(void)) sr;
-+ }
-+
-+ return(copy_to_user((void *) (start + sr_index), &restorer,
-+ sizeof(restorer)));
-+}
-+
-+extern int userspace_pid[];
-+
-+static int copy_sc_to_user(void *to, void *fp, struct pt_regs *from,
-+ struct arch_frame_data *arch)
-+{
-+ return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
-+ arch),
-+ copy_sc_to_user_skas(userspace_pid[0], to, fp,
-+ &from->regs,
-+ current->thread.cr2,
-+ current->thread.err)));
-+}
-+
-+static int copy_ucontext_to_user(struct ucontext *uc, void *fp, sigset_t *set,
-+ unsigned long sp)
-+{
-+ int err = 0;
-+
-+ err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp);
-+ err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags);
-+ err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size);
-+ err |= copy_sc_to_user(&uc->uc_mcontext, fp, ¤t->thread.regs,
-+ &signal_frame_si.common.arch);
-+ err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set));
-+ return(err);
-+}
-+
-+int setup_signal_stack_si(unsigned long stack_top, int sig,
-+ unsigned long handler, void (*restorer)(void),
-+ struct pt_regs *regs, siginfo_t *info,
-+ sigset_t *mask)
-+{
-+ unsigned long start;
-+ void *sip, *ucp, *fp;
-+
-+ start = stack_top - signal_frame_si.common.len;
-+ sip = (void *) (start + signal_frame_si.si_index);
-+ ucp = (void *) (start + signal_frame_si.uc_index);
-+ fp = (void *) (((unsigned long) ucp) + sizeof(struct ucontext));
-+
-+ if(restorer == NULL)
-+ panic("setup_signal_stack_si - no restorer");
-+
-+ if(copy_to_user((void *) start, signal_frame_si.common.data,
-+ signal_frame_si.common.len) ||
-+ copy_to_user((void *) (start + signal_frame_si.common.sig_index),
-+ &sig, sizeof(sig)) ||
-+ copy_siginfo_to_user(sip, info) ||
-+ copy_to_user((void *) (start + signal_frame_si.sip_index), &sip,
-+ sizeof(sip)) ||
-+ copy_ucontext_to_user(ucp, fp, mask, PT_REGS_SP(regs)) ||
-+ copy_to_user((void *) (start + signal_frame_si.ucp_index), &ucp,
-+ sizeof(ucp)) ||
-+ copy_restorer(restorer, start, signal_frame_si.common.sr_index,
-+ signal_frame_si.common.sr_relative))
-+ return(1);
-+
-+ PT_REGS_IP(regs) = handler;
-+ PT_REGS_SP(regs) = start + signal_frame_si.common.sp_index;
-+ return(0);
-+}
-+
-+int setup_signal_stack_sc(unsigned long stack_top, int sig,
-+ unsigned long handler, void (*restorer)(void),
-+ struct pt_regs *regs, sigset_t *mask)
-+{
-+ struct frame_common *frame = &signal_frame_sc_sr.common;
-+ void *user_sc;
-+ int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
-+ unsigned long sigs, sr;
-+ unsigned long start = stack_top - frame->len - sig_size;
-+
-+ user_sc = (void *) (start + signal_frame_sc_sr.sc_index);
-+ if(restorer == NULL){
-+ frame = &signal_frame_sc.common;
-+ user_sc = (void *) (start + signal_frame_sc.sc_index);
-+ sr = (unsigned long) frame->data;
-+ sr += frame->sr_index;
-+ sr = *((unsigned long *) sr);
-+ restorer = ((void (*)(void)) sr);
-+ }
-+
-+ sigs = start + frame->len;
-+ if(copy_to_user((void *) start, frame->data, frame->len) ||
-+ copy_to_user((void *) (start + frame->sig_index), &sig,
-+ sizeof(sig)) ||
-+ copy_sc_to_user(user_sc, NULL, regs,
-+ &signal_frame_sc.common.arch) ||
-+ copy_to_user(sc_sigmask(user_sc), mask, sizeof(mask->sig[0])) ||
-+ copy_to_user((void *) sigs, &mask->sig[1], sig_size) ||
-+ copy_restorer(restorer, start, frame->sr_index, frame->sr_relative))
-+ return(1);
-+
-+ PT_REGS_IP(regs) = handler;
-+ PT_REGS_SP(regs) = start + frame->sp_index;
-+
-+ return(0);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/gmon_syms.c um/arch/um/kernel/gmon_syms.c
---- orig/arch/um/kernel/gmon_syms.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/gmon_syms.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,20 @@
-+/*
-+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/module.h"
-+
-+extern void __bb_init_func(void *);
-+EXPORT_SYMBOL(__bb_init_func);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/gprof_syms.c um/arch/um/kernel/gprof_syms.c
---- orig/arch/um/kernel/gprof_syms.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/gprof_syms.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,20 @@
-+/*
-+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/module.h"
-+
-+extern void mcount(void);
-+EXPORT_SYMBOL(mcount);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/helper.c um/arch/um/kernel/helper.c
---- orig/arch/um/kernel/helper.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/helper.c 2003-11-08 07:41:30.000000000 -0500
-@@ -0,0 +1,170 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <errno.h>
-+#include <sched.h>
-+#include <sys/signal.h>
-+#include <sys/wait.h>
-+#include "user.h"
-+#include "kern_util.h"
-+#include "os.h"
-+
-+struct helper_data {
-+ void (*pre_exec)(void*);
-+ void *pre_data;
-+ char **argv;
-+ int fd;
-+};
-+
-+/* Debugging aid, changed only from gdb */
-+int helper_pause = 0;
-+
-+static void helper_hup(int sig)
-+{
-+}
-+
-+static int helper_child(void *arg)
-+{
-+ struct helper_data *data = arg;
-+ char **argv = data->argv;
-+ int errval;
-+
-+ if(helper_pause){
-+ signal(SIGHUP, helper_hup);
-+ pause();
-+ }
-+ if(data->pre_exec != NULL)
-+ (*data->pre_exec)(data->pre_data);
-+ execvp(argv[0], argv);
-+ errval = errno;
-+ printk("execvp of '%s' failed - errno = %d\n", argv[0], errno);
-+ os_write_file(data->fd, &errval, sizeof(errval));
-+ os_kill_process(os_getpid(), 0);
-+ return(0);
-+}
-+
-+/* XXX The alloc_stack here breaks if this is called in the tracing thread */
-+
-+int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
-+ unsigned long *stack_out)
-+{
-+ struct helper_data data;
-+ unsigned long stack, sp;
-+ int pid, fds[2], err, n;
-+
-+ if((stack_out != NULL) && (*stack_out != 0))
-+ stack = *stack_out;
-+ else stack = alloc_stack(0, um_in_interrupt());
-+ if(stack == 0)
-+ return(-ENOMEM);
-+
-+ err = os_pipe(fds, 1, 0);
-+ if(err < 0){
-+ printk("run_helper : pipe failed, err = %d\n", -err);
-+ goto out_free;
-+ }
-+
-+ err = os_set_exec_close(fds[1], 1);
-+ if(err < 0){
-+ printk("run_helper : setting FD_CLOEXEC failed, err = %d\n",
-+ -err);
-+ goto out_close;
-+ }
-+
-+ sp = stack + page_size() - sizeof(void *);
-+ data.pre_exec = pre_exec;
-+ data.pre_data = pre_data;
-+ data.argv = argv;
-+ data.fd = fds[1];
-+ pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
-+ if(pid < 0){
-+ printk("run_helper : clone failed, errno = %d\n", errno);
-+ err = -errno;
-+ goto out_close;
-+ }
-+
-+ os_close_file(fds[1]);
-+ n = os_read_file(fds[0], &err, sizeof(err));
-+ if(n < 0){
-+ printk("run_helper : read on pipe failed, err = %d\n", -n);
-+ err = n;
-+ goto out_kill;
-+ }
-+ else if(n != 0){
-+ waitpid(pid, NULL, 0);
-+ pid = -errno;
-+ }
-+
-+ if(stack_out == NULL) free_stack(stack, 0);
-+ else *stack_out = stack;
-+ return(pid);
-+
-+ out_kill:
-+ os_kill_process(pid, 1);
-+ out_close:
-+ os_close_file(fds[0]);
-+ os_close_file(fds[1]);
-+ out_free:
-+ free_stack(stack, 0);
-+ return(err);
-+}
-+
-+int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
-+ unsigned long *stack_out, int stack_order)
-+{
-+ unsigned long stack, sp;
-+ int pid, status;
-+
-+ stack = alloc_stack(stack_order, um_in_interrupt());
-+ if(stack == 0) return(-ENOMEM);
-+
-+ sp = stack + (page_size() << stack_order) - sizeof(void *);
-+ pid = clone(proc, (void *) sp, flags | SIGCHLD, arg);
-+ if(pid < 0){
-+ printk("run_helper_thread : clone failed, errno = %d\n",
-+ errno);
-+ return(-errno);
-+ }
-+ if(stack_out == NULL){
-+ pid = waitpid(pid, &status, 0);
-+ if(pid < 0){
-+ printk("run_helper_thread - wait failed, errno = %d\n",
-+ errno);
-+ pid = -errno;
-+ }
-+ if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
-+ printk("run_helper_thread - thread returned status "
-+ "0x%x\n", status);
-+ free_stack(stack, stack_order);
-+ }
-+ else *stack_out = stack;
-+ return(pid);
-+}
-+
-+int helper_wait(int pid, int block)
-+{
-+ int ret;
-+
-+ ret = waitpid(pid, NULL, WNOHANG);
-+ if(ret < 0){
-+ printk("helper_wait : waitpid failed, errno = %d\n", errno);
-+ return(-errno);
-+ }
-+ return(ret);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/initrd_kern.c um/arch/um/kernel/initrd_kern.c
---- orig/arch/um/kernel/initrd_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/initrd_kern.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,59 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/init.h"
-+#include "linux/bootmem.h"
-+#include "linux/blk.h"
-+#include "asm/types.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "initrd.h"
-+#include "init.h"
-+#include "os.h"
-+
-+/* Changed by uml_initrd_setup, which is a setup */
-+static char *initrd __initdata = NULL;
-+
-+static int __init read_initrd(void)
-+{
-+ void *area;
-+ long long size;
-+ int err;
-+
-+ if(initrd == NULL) return 0;
-+ err = os_file_size(initrd, &size);
-+ if(err) return 0;
-+ area = alloc_bootmem(size);
-+ if(area == NULL) return 0;
-+ if(load_initrd(initrd, area, size) == -1) return 0;
-+ initrd_start = (unsigned long) area;
-+ initrd_end = initrd_start + size;
-+ return 0;
-+}
-+
-+__uml_postsetup(read_initrd);
-+
-+static int __init uml_initrd_setup(char *line, int *add)
-+{
-+ initrd = line;
-+ return 0;
-+}
-+
-+__uml_setup("initrd=", uml_initrd_setup,
-+"initrd=<initrd image>\n"
-+" This is used to boot UML from an initrd image. The argument is the\n"
-+" name of the file containing the image.\n\n"
-+);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/initrd_user.c um/arch/um/kernel/initrd_user.c
---- orig/arch/um/kernel/initrd_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/initrd_user.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,44 @@
-+/*
-+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <unistd.h>
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <errno.h>
-+
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "user.h"
-+#include "initrd.h"
-+#include "os.h"
-+
-+int load_initrd(char *filename, void *buf, int size)
-+{
-+ int fd, n;
-+
-+ fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
-+ if(fd < 0){
-+ printk("Opening '%s' failed - err = %d\n", filename, -fd);
-+ return(-1);
-+ }
-+ n = os_read_file(fd, buf, size);
-+ if(n != size){
-+ printk("Read of %d bytes from '%s' failed, err = %d\n", size,
-+ filename, -n);
-+ return(-1);
-+ }
-+ return(0);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/init_task.c um/arch/um/kernel/init_task.c
---- orig/arch/um/kernel/init_task.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/init_task.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,61 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/config.h"
-+#include "linux/mm.h"
-+#include "linux/sched.h"
-+#include "linux/version.h"
-+#include "asm/uaccess.h"
-+#include "asm/pgtable.h"
-+#include "user_util.h"
-+#include "mem_user.h"
-+
-+static struct fs_struct init_fs = INIT_FS;
-+static struct files_struct init_files = INIT_FILES;
-+static struct signal_struct init_signals = INIT_SIGNALS;
-+struct mm_struct init_mm = INIT_MM(init_mm);
-+
-+/*
-+ * Initial task structure.
-+ *
-+ * We need to make sure that this is 16384-byte aligned due to the
-+ * way process stacks are handled. This is done by having a special
-+ * "init_task" linker map entry..
-+ */
-+
-+union task_union init_task_union
-+__attribute__((__section__(".data.init_task"))) =
-+{ INIT_TASK(init_task_union.task) };
-+
-+struct task_struct *alloc_task_struct(void)
-+{
-+ return((struct task_struct *)
-+ __get_free_pages(GFP_KERNEL, CONFIG_KERNEL_STACK_ORDER));
-+}
-+
-+void unprotect_stack(unsigned long stack)
-+{
-+ protect_memory(stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE,
-+ 1, 1, 0, 1);
-+}
-+
-+void free_task_struct(struct task_struct *task)
-+{
-+ /* free_pages decrements the page counter and only actually frees
-+ * the pages if they are now not accessed by anything.
-+ */
-+ free_pages((unsigned long) task, CONFIG_KERNEL_STACK_ORDER);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/irq.c um/arch/um/kernel/irq.c
---- orig/arch/um/kernel/irq.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/irq.c 2003-12-16 22:45:27.000000000 -0500
-@@ -0,0 +1,840 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ * Derived (i.e. mostly copied) from arch/i386/kernel/irq.c:
-+ * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
-+ */
-+
-+#include "linux/config.h"
-+#include "linux/kernel.h"
-+#include "linux/smp.h"
-+#include "linux/irq.h"
-+#include "linux/kernel_stat.h"
-+#include "linux/interrupt.h"
-+#include "linux/random.h"
-+#include "linux/slab.h"
-+#include "linux/file.h"
-+#include "linux/proc_fs.h"
-+#include "linux/init.h"
-+#include "linux/seq_file.h"
-+#include "asm/irq.h"
-+#include "asm/hw_irq.h"
-+#include "asm/hardirq.h"
-+#include "asm/atomic.h"
-+#include "asm/signal.h"
-+#include "asm/system.h"
-+#include "asm/errno.h"
-+#include "asm/uaccess.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "irq_user.h"
-+#include "irq_kern.h"
-+
-+static void register_irq_proc (unsigned int irq);
-+
-+irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned =
-+ { [0 ... NR_IRQS-1] = { 0, &no_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED}};
-+
-+/*
-+ * Generic no controller code
-+ */
-+
-+static void enable_none(unsigned int irq) { }
-+static unsigned int startup_none(unsigned int irq) { return 0; }
-+static void disable_none(unsigned int irq) { }
-+static void ack_none(unsigned int irq)
-+{
-+/*
-+ * 'what should we do if we get a hw irq event on an illegal vector'.
-+ * each architecture has to answer this themselves, it doesnt deserve
-+ * a generic callback i think.
-+ */
-+#if CONFIG_X86
-+ printk(KERN_ERR "unexpected IRQ trap at vector %02x\n", irq);
-+#ifdef CONFIG_X86_LOCAL_APIC
-+ /*
-+ * Currently unexpected vectors happen only on SMP and APIC.
-+ * We _must_ ack these because every local APIC has only N
-+ * irq slots per priority level, and a 'hanging, unacked' IRQ
-+ * holds up an irq slot - in excessive cases (when multiple
-+ * unexpected vectors occur) that might lock up the APIC
-+ * completely.
-+ */
-+ ack_APIC_irq();
-+#endif
-+#endif
-+}
-+
-+/* startup is the same as "enable", shutdown is same as "disable" */
-+#define shutdown_none disable_none
-+#define end_none enable_none
-+
-+struct hw_interrupt_type no_irq_type = {
-+ "none",
-+ startup_none,
-+ shutdown_none,
-+ enable_none,
-+ disable_none,
-+ ack_none,
-+ end_none
-+};
-+
-+/*
-+ * Generic, controller-independent functions:
-+ */
-+
-+int get_irq_list(char *buf)
-+{
-+ int i, j;
-+ unsigned long flags;
-+ struct irqaction * action;
-+ char *p = buf;
-+
-+ p += sprintf(p, " ");
-+ for (j=0; j<smp_num_cpus; j++)
-+ p += sprintf(p, "CPU%d ",j);
-+ *p++ = '\n';
-+
-+ for (i = 0 ; i < NR_IRQS ; i++) {
-+ spin_lock_irqsave(&irq_desc[i].lock, flags);
-+ action = irq_desc[i].action;
-+ if (!action)
-+ goto end;
-+ p += sprintf(p, "%3d: ",i);
-+#ifndef CONFIG_SMP
-+ p += sprintf(p, "%10u ", kstat_irqs(i));
-+#else
-+ for (j = 0; j < smp_num_cpus; j++)
-+ p += sprintf(p, "%10u ",
-+ kstat.irqs[cpu_logical_map(j)][i]);
-+#endif
-+ p += sprintf(p, " %14s", irq_desc[i].handler->typename);
-+ p += sprintf(p, " %s", action->name);
-+
-+ for (action=action->next; action; action = action->next)
-+ p += sprintf(p, ", %s", action->name);
-+ *p++ = '\n';
-+ end:
-+ spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-+ }
-+ p += sprintf(p, "\n");
-+#ifdef notdef
-+#if CONFIG_SMP
-+ p += sprintf(p, "LOC: ");
-+ for (j = 0; j < smp_num_cpus; j++)
-+ p += sprintf(p, "%10u ",
-+ apic_timer_irqs[cpu_logical_map(j)]);
-+ p += sprintf(p, "\n");
-+#endif
-+#endif
-+ p += sprintf(p, "ERR: %10lu\n", 0L);
-+ return p - buf;
-+}
-+
-+/*
-+ * This should really return information about whether
-+ * we should do bottom half handling etc. Right now we
-+ * end up _always_ checking the bottom half, which is a
-+ * waste of time and is not what some drivers would
-+ * prefer.
-+ */
-+int handle_IRQ_event(unsigned int irq, struct pt_regs * regs,
-+ struct irqaction * action)
-+{
-+ int status;
-+ int cpu = smp_processor_id();
-+
-+ irq_enter(cpu, irq);
-+
-+ status = 1; /* Force the "do bottom halves" bit */
-+
-+ if (!(action->flags & SA_INTERRUPT))
-+ __sti();
-+
-+ do {
-+ status |= action->flags;
-+ action->handler(irq, action->dev_id, regs);
-+ action = action->next;
-+ } while (action);
-+ if (status & SA_SAMPLE_RANDOM)
-+ add_interrupt_randomness(irq);
-+ __cli();
-+
-+ irq_exit(cpu, irq);
-+
-+ return status;
-+}
-+
-+/*
-+ * Generic enable/disable code: this just calls
-+ * down into the PIC-specific version for the actual
-+ * hardware disable after having gotten the irq
-+ * controller lock.
-+ */
-+
-+/**
-+ * disable_irq_nosync - disable an irq without waiting
-+ * @irq: Interrupt to disable
-+ *
-+ * Disable the selected interrupt line. Disables of an interrupt
-+ * stack. Unlike disable_irq(), this function does not ensure existing
-+ * instances of the IRQ handler have completed before returning.
-+ *
-+ * This function may be called from IRQ context.
-+ */
-+
-+void inline disable_irq_nosync(unsigned int irq)
-+{
-+ irq_desc_t *desc = irq_desc + irq;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&desc->lock, flags);
-+ if (!desc->depth++) {
-+ desc->status |= IRQ_DISABLED;
-+ desc->handler->disable(irq);
-+ }
-+ spin_unlock_irqrestore(&desc->lock, flags);
-+}
-+
-+/**
-+ * disable_irq - disable an irq and wait for completion
-+ * @irq: Interrupt to disable
-+ *
-+ * Disable the selected interrupt line. Disables of an interrupt
-+ * stack. That is for two disables you need two enables. This
-+ * function waits for any pending IRQ handlers for this interrupt
-+ * to complete before returning. If you use this function while
-+ * holding a resource the IRQ handler may need you will deadlock.
-+ *
-+ * This function may be called - with care - from IRQ context.
-+ */
-+
-+void disable_irq(unsigned int irq)
-+{
-+ disable_irq_nosync(irq);
-+
-+ if (!local_irq_count(smp_processor_id())) {
-+ do {
-+ barrier();
-+ } while (irq_desc[irq].status & IRQ_INPROGRESS);
-+ }
-+}
-+
-+/**
-+ * enable_irq - enable interrupt handling on an irq
-+ * @irq: Interrupt to enable
-+ *
-+ * Re-enables the processing of interrupts on this IRQ line
-+ * providing no disable_irq calls are now in effect.
-+ *
-+ * This function may be called from IRQ context.
-+ */
-+
-+void enable_irq(unsigned int irq)
-+{
-+ irq_desc_t *desc = irq_desc + irq;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&desc->lock, flags);
-+ switch (desc->depth) {
-+ case 1: {
-+ unsigned int status = desc->status & ~IRQ_DISABLED;
-+ desc->status = status;
-+ if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
-+ desc->status = status | IRQ_REPLAY;
-+ hw_resend_irq(desc->handler,irq);
-+ }
-+ desc->handler->enable(irq);
-+ /* fall-through */
-+ }
-+ default:
-+ desc->depth--;
-+ break;
-+ case 0:
-+ printk(KERN_ERR "enable_irq() unbalanced from %p\n",
-+ __builtin_return_address(0));
-+ }
-+ spin_unlock_irqrestore(&desc->lock, flags);
-+}
-+
-+/*
-+ * do_IRQ handles all normal device IRQ's (the special
-+ * SMP cross-CPU interrupts have their own specific
-+ * handlers).
-+ */
-+unsigned int do_IRQ(int irq, union uml_pt_regs *regs)
-+{
-+ /*
-+ * 0 return value means that this irq is already being
-+ * handled by some other CPU. (or is disabled)
-+ */
-+ int cpu = smp_processor_id();
-+ irq_desc_t *desc = irq_desc + irq;
-+ struct irqaction * action;
-+ unsigned int status;
-+
-+ kstat.irqs[cpu][irq]++;
-+ spin_lock(&desc->lock);
-+ desc->handler->ack(irq);
-+ /*
-+ REPLAY is when Linux resends an IRQ that was dropped earlier
-+ WAITING is used by probe to mark irqs that are being tested
-+ */
-+ status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
-+ status |= IRQ_PENDING; /* we _want_ to handle it */
-+
-+ /*
-+ * If the IRQ is disabled for whatever reason, we cannot
-+ * use the action we have.
-+ */
-+ action = NULL;
-+ if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
-+ action = desc->action;
-+ status &= ~IRQ_PENDING; /* we commit to handling */
-+ status |= IRQ_INPROGRESS; /* we are handling it */
-+ }
-+ desc->status = status;
-+
-+ /*
-+ * If there is no IRQ handler or it was disabled, exit early.
-+ Since we set PENDING, if another processor is handling
-+ a different instance of this same irq, the other processor
-+ will take care of it.
-+ */
-+ if (!action)
-+ goto out;
-+
-+ /*
-+ * Edge triggered interrupts need to remember
-+ * pending events.
-+ * This applies to any hw interrupts that allow a second
-+ * instance of the same irq to arrive while we are in do_IRQ
-+ * or in the handler. But the code here only handles the _second_
-+ * instance of the irq, not the third or fourth. So it is mostly
-+ * useful for irq hardware that does not mask cleanly in an
-+ * SMP environment.
-+ */
-+ for (;;) {
-+ spin_unlock(&desc->lock);
-+ handle_IRQ_event(irq, (struct pt_regs *) regs, action);
-+ spin_lock(&desc->lock);
-+
-+ if (!(desc->status & IRQ_PENDING))
-+ break;
-+ desc->status &= ~IRQ_PENDING;
-+ }
-+ desc->status &= ~IRQ_INPROGRESS;
-+out:
-+ /*
-+ * The ->end() handler has to deal with interrupts which got
-+ * disabled while the handler was running.
-+ */
-+ desc->handler->end(irq);
-+ spin_unlock(&desc->lock);
-+
-+ if (softirq_pending(cpu))
-+ do_softirq();
-+ return 1;
-+}
-+
-+/**
-+ * request_irq - allocate an interrupt line
-+ * @irq: Interrupt line to allocate
-+ * @handler: Function to be called when the IRQ occurs
-+ * @irqflags: Interrupt type flags
-+ * @devname: An ascii name for the claiming device
-+ * @dev_id: A cookie passed back to the handler function
-+ *
-+ * This call allocates interrupt resources and enables the
-+ * interrupt line and IRQ handling. From the point this
-+ * call is made your handler function may be invoked. Since
-+ * your handler function must clear any interrupt the board
-+ * raises, you must take care both to initialise your hardware
-+ * and to set up the interrupt handler in the right order.
-+ *
-+ * Dev_id must be globally unique. Normally the address of the
-+ * device data structure is used as the cookie. Since the handler
-+ * receives this value it makes sense to use it.
-+ *
-+ * If your interrupt is shared you must pass a non NULL dev_id
-+ * as this is required when freeing the interrupt.
-+ *
-+ * Flags:
-+ *
-+ * SA_SHIRQ Interrupt is shared
-+ *
-+ * SA_INTERRUPT Disable local interrupts while processing
-+ *
-+ * SA_SAMPLE_RANDOM The interrupt can be used for entropy
-+ *
-+ */
-+
-+int request_irq(unsigned int irq,
-+ void (*handler)(int, void *, struct pt_regs *),
-+ unsigned long irqflags,
-+ const char * devname,
-+ void *dev_id)
-+{
-+ int retval;
-+ struct irqaction * action;
-+
-+#if 1
-+ /*
-+ * Sanity-check: shared interrupts should REALLY pass in
-+ * a real dev-ID, otherwise we'll have trouble later trying
-+ * to figure out which interrupt is which (messes up the
-+ * interrupt freeing logic etc).
-+ */
-+ if (irqflags & SA_SHIRQ) {
-+ if (!dev_id)
-+ printk(KERN_ERR "Bad boy: %s (at 0x%x) called us "
-+ "without a dev_id!\n", devname, (&irq)[-1]);
-+ }
-+#endif
-+
-+ if (irq >= NR_IRQS)
-+ return -EINVAL;
-+ if (!handler)
-+ return -EINVAL;
-+
-+ action = (struct irqaction *)
-+ kmalloc(sizeof(struct irqaction), GFP_KERNEL);
-+ if (!action)
-+ return -ENOMEM;
-+
-+ action->handler = handler;
-+ action->flags = irqflags;
-+ action->mask = 0;
-+ action->name = devname;
-+ action->next = NULL;
-+ action->dev_id = dev_id;
-+
-+ retval = setup_irq(irq, action);
-+ if (retval)
-+ kfree(action);
-+ return retval;
-+}
-+
-+int um_request_irq(unsigned int irq, int fd, int type,
-+ void (*handler)(int, void *, struct pt_regs *),
-+ unsigned long irqflags, const char * devname,
-+ void *dev_id)
-+{
-+ int err;
-+
-+ err = request_irq(irq, handler, irqflags, devname, dev_id);
-+ if(err)
-+ return(err);
-+
-+ if(fd != -1)
-+ err = activate_fd(irq, fd, type, dev_id);
-+ return(err);
-+}
-+
-+/* this was setup_x86_irq but it seems pretty generic */
-+int setup_irq(unsigned int irq, struct irqaction * new)
-+{
-+ int shared = 0;
-+ unsigned long flags;
-+ struct irqaction *old, **p;
-+ irq_desc_t *desc = irq_desc + irq;
-+
-+ /*
-+ * Some drivers like serial.c use request_irq() heavily,
-+ * so we have to be careful not to interfere with a
-+ * running system.
-+ */
-+ if (new->flags & SA_SAMPLE_RANDOM) {
-+ /*
-+ * This function might sleep, we want to call it first,
-+ * outside of the atomic block.
-+ * Yes, this might clear the entropy pool if the wrong
-+ * driver is attempted to be loaded, without actually
-+ * installing a new handler, but is this really a problem,
-+ * only the sysadmin is able to do this.
-+ */
-+ rand_initialize_irq(irq);
-+ }
-+
-+ /*
-+ * The following block of code has to be executed atomically
-+ */
-+ spin_lock_irqsave(&desc->lock,flags);
-+ p = &desc->action;
-+ old = *p;
-+ if (old != NULL) {
-+ /* Can't share interrupts unless both agree to */
-+ if (!(old->flags & new->flags & SA_SHIRQ)) {
-+ spin_unlock_irqrestore(&desc->lock,flags);
-+ return -EBUSY;
-+ }
-+
-+ /* add new interrupt at end of irq queue */
-+ do {
-+ p = &old->next;
-+ old = *p;
-+ } while (old);
-+ shared = 1;
-+ }
-+
-+ *p = new;
-+
-+ if (!shared) {
-+ desc->depth = 0;
-+ desc->status &= ~IRQ_DISABLED;
-+ desc->handler->startup(irq);
-+ }
-+ spin_unlock_irqrestore(&desc->lock,flags);
-+
-+ register_irq_proc(irq);
-+ return 0;
-+}
-+
-+/**
-+ * free_irq - free an interrupt
-+ * @irq: Interrupt line to free
-+ * @dev_id: Device identity to free
-+ *
-+ * Remove an interrupt handler. The handler is removed and if the
-+ * interrupt line is no longer in use by any driver it is disabled.
-+ * On a shared IRQ the caller must ensure the interrupt is disabled
-+ * on the card it drives before calling this function. The function
-+ * does not return until any executing interrupts for this IRQ
-+ * have completed.
-+ *
-+ * This function may be called from interrupt context.
-+ *
-+ * Bugs: Attempting to free an irq in a handler for the same irq hangs
-+ * the machine.
-+ */
-+
-+void free_irq(unsigned int irq, void *dev_id)
-+{
-+ irq_desc_t *desc;
-+ struct irqaction **p;
-+ unsigned long flags;
-+
-+ if (irq >= NR_IRQS)
-+ return;
-+
-+ desc = irq_desc + irq;
-+ spin_lock_irqsave(&desc->lock,flags);
-+ p = &desc->action;
-+ for (;;) {
-+ struct irqaction * action = *p;
-+ if (action) {
-+ struct irqaction **pp = p;
-+ p = &action->next;
-+ if (action->dev_id != dev_id)
-+ continue;
-+
-+ /* Found it - now remove it from the list of entries */
-+ *pp = action->next;
-+ if (!desc->action) {
-+ desc->status |= IRQ_DISABLED;
-+ desc->handler->shutdown(irq);
-+ }
-+ free_irq_by_irq_and_dev(irq, dev_id);
-+ spin_unlock_irqrestore(&desc->lock,flags);
-+
-+#ifdef CONFIG_SMP
-+ /* Wait to make sure it's not being used on another CPU */
-+ while (desc->status & IRQ_INPROGRESS)
-+ barrier();
-+#endif
-+ kfree(action);
-+ return;
-+ }
-+ printk(KERN_ERR "Trying to free free IRQ%d\n",irq);
-+ spin_unlock_irqrestore(&desc->lock,flags);
-+ return;
-+ }
-+}
-+
-+/* These are initialized by sysctl_init, which is called from init/main.c */
-+static struct proc_dir_entry * root_irq_dir;
-+static struct proc_dir_entry * irq_dir [NR_IRQS];
-+static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
-+
-+/* These are read and written as longs, so a read won't see a partial write
-+ * even during a race.
-+ */
-+static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
-+
-+#define HEX_DIGITS 8
-+
-+static int irq_affinity_read_proc (char *page, char **start, off_t off,
-+ int count, int *eof, void *data)
-+{
-+ if (count < HEX_DIGITS+1)
-+ return -EINVAL;
-+ return sprintf (page, "%08lx\n", irq_affinity[(long)data]);
-+}
-+
-+static unsigned int parse_hex_value (const char *buffer,
-+ unsigned long count, unsigned long *ret)
-+{
-+ unsigned char hexnum [HEX_DIGITS];
-+ unsigned long value;
-+ int i;
-+
-+ if (!count)
-+ return -EINVAL;
-+ if (count > HEX_DIGITS)
-+ count = HEX_DIGITS;
-+ if (copy_from_user(hexnum, buffer, count))
-+ return -EFAULT;
-+
-+ /*
-+ * Parse the first HEX_DIGITS characters as a hex string, any non-hex
-+ * char is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same.
-+ */
-+ value = 0;
-+
-+ for (i = 0; i < count; i++) {
-+ unsigned int c = hexnum[i];
-+
-+ switch (c) {
-+ case '0' ... '9': c -= '0'; break;
-+ case 'a' ... 'f': c -= 'a'-10; break;
-+ case 'A' ... 'F': c -= 'A'-10; break;
-+ default:
-+ goto out;
-+ }
-+ value = (value << 4) | c;
-+ }
-+out:
-+ *ret = value;
-+ return 0;
-+}
-+
-+static int irq_affinity_write_proc (struct file *file, const char *buffer,
-+ unsigned long count, void *data)
-+{
-+ int irq = (long) data, full_count = count, err;
-+ unsigned long new_value;
-+
-+ if (!irq_desc[irq].handler->set_affinity)
-+ return -EIO;
-+
-+ err = parse_hex_value(buffer, count, &new_value);
-+
-+#if CONFIG_SMP
-+ /*
-+ * Do not allow disabling IRQs completely - it's a too easy
-+ * way to make the system unusable accidentally :-) At least
-+ * one online CPU still has to be targeted.
-+ */
-+ if (!(new_value & cpu_online_map))
-+ return -EINVAL;
-+#endif
-+
-+ irq_affinity[irq] = new_value;
-+ irq_desc[irq].handler->set_affinity(irq, new_value);
-+
-+ return full_count;
-+}
-+
-+static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
-+ int count, int *eof, void *data)
-+{
-+ unsigned long *mask = (unsigned long *) data;
-+ if (count < HEX_DIGITS+1)
-+ return -EINVAL;
-+ return sprintf (page, "%08lx\n", *mask);
-+}
-+
-+static int prof_cpu_mask_write_proc (struct file *file, const char *buffer,
-+ unsigned long count, void *data)
-+{
-+ unsigned long *mask = (unsigned long *) data, full_count = count, err;
-+ unsigned long new_value;
-+
-+ err = parse_hex_value(buffer, count, &new_value);
-+ if (err)
-+ return err;
-+
-+ *mask = new_value;
-+ return full_count;
-+}
-+
-+#define MAX_NAMELEN 10
-+
-+static void register_irq_proc (unsigned int irq)
-+{
-+ struct proc_dir_entry *entry;
-+ char name [MAX_NAMELEN];
-+
-+ if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) ||
-+ irq_dir[irq])
-+ return;
-+
-+ memset(name, 0, MAX_NAMELEN);
-+ sprintf(name, "%d", irq);
-+
-+ /* create /proc/irq/1234 */
-+ irq_dir[irq] = proc_mkdir(name, root_irq_dir);
-+
-+ /* create /proc/irq/1234/smp_affinity */
-+ entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
-+
-+ entry->nlink = 1;
-+ entry->data = (void *)(long)irq;
-+ entry->read_proc = irq_affinity_read_proc;
-+ entry->write_proc = irq_affinity_write_proc;
-+
-+ smp_affinity_entry[irq] = entry;
-+}
-+
-+/* Read and written as a long */
-+unsigned long prof_cpu_mask = -1;
-+
-+void __init init_irq_proc (void)
-+{
-+ struct proc_dir_entry *entry;
-+ int i;
-+
-+ /* create /proc/irq */
-+ root_irq_dir = proc_mkdir("irq", 0);
-+
-+ /* create /proc/irq/prof_cpu_mask */
-+ entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
-+
-+ entry->nlink = 1;
-+ entry->data = (void *)&prof_cpu_mask;
-+ entry->read_proc = prof_cpu_mask_read_proc;
-+ entry->write_proc = prof_cpu_mask_write_proc;
-+
-+ /*
-+ * Create entries for all existing IRQs.
-+ */
-+ for (i = 0; i < NR_IRQS; i++)
-+ register_irq_proc(i);
-+}
-+
-+static spinlock_t irq_spinlock = SPIN_LOCK_UNLOCKED;
-+
-+unsigned long irq_lock(void)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&irq_spinlock, flags);
-+ return(flags);
-+}
-+
-+void irq_unlock(unsigned long flags)
-+{
-+ spin_unlock_irqrestore(&irq_spinlock, flags);
-+}
-+
-+unsigned long probe_irq_on(void)
-+{
-+ return(0);
-+}
-+
-+int probe_irq_off(unsigned long val)
-+{
-+ return(0);
-+}
-+
-+static unsigned int startup_SIGIO_irq(unsigned int irq)
-+{
-+ return(0);
-+}
-+
-+static void shutdown_SIGIO_irq(unsigned int irq)
-+{
-+}
-+
-+static void enable_SIGIO_irq(unsigned int irq)
-+{
-+}
-+
-+static void disable_SIGIO_irq(unsigned int irq)
-+{
-+}
-+
-+static void mask_and_ack_SIGIO(unsigned int irq)
-+{
-+}
-+
-+static void end_SIGIO_irq(unsigned int irq)
-+{
-+}
-+
-+static unsigned int startup_SIGVTALRM_irq(unsigned int irq)
-+{
-+ return(0);
-+}
-+
-+static void shutdown_SIGVTALRM_irq(unsigned int irq)
-+{
-+}
-+
-+static void enable_SIGVTALRM_irq(unsigned int irq)
-+{
-+}
-+
-+static void disable_SIGVTALRM_irq(unsigned int irq)
-+{
-+}
-+
-+static void mask_and_ack_SIGVTALRM(unsigned int irq)
-+{
-+}
-+
-+static void end_SIGVTALRM_irq(unsigned int irq)
-+{
-+}
-+
-+static struct hw_interrupt_type SIGIO_irq_type = {
-+ "SIGIO",
-+ startup_SIGIO_irq,
-+ shutdown_SIGIO_irq,
-+ enable_SIGIO_irq,
-+ disable_SIGIO_irq,
-+ mask_and_ack_SIGIO,
-+ end_SIGIO_irq,
-+ NULL
-+};
-+
-+static struct hw_interrupt_type SIGVTALRM_irq_type = {
-+ "SIGVTALRM",
-+ startup_SIGVTALRM_irq,
-+ shutdown_SIGVTALRM_irq,
-+ enable_SIGVTALRM_irq,
-+ disable_SIGVTALRM_irq,
-+ mask_and_ack_SIGVTALRM,
-+ end_SIGVTALRM_irq,
-+ NULL
-+};
-+
-+void __init init_IRQ(void)
-+{
-+ int i;
-+
-+ irq_desc[TIMER_IRQ].status = IRQ_DISABLED;
-+ irq_desc[TIMER_IRQ].action = 0;
-+ irq_desc[TIMER_IRQ].depth = 1;
-+ irq_desc[TIMER_IRQ].handler = &SIGVTALRM_irq_type;
-+ enable_irq(TIMER_IRQ);
-+ for(i=1;i<NR_IRQS;i++){
-+ irq_desc[i].status = IRQ_DISABLED;
-+ irq_desc[i].action = 0;
-+ irq_desc[i].depth = 1;
-+ irq_desc[i].handler = &SIGIO_irq_type;
-+ enable_irq(i);
-+ }
-+ init_irq_signals(0);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/irq_user.c um/arch/um/kernel/irq_user.c
---- orig/arch/um/kernel/irq_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/irq_user.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,424 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <errno.h>
-+#include <signal.h>
-+#include <string.h>
-+#include <sys/poll.h>
-+#include <sys/types.h>
-+#include <sys/time.h>
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "user.h"
-+#include "process.h"
-+#include "signal_user.h"
-+#include "sigio.h"
-+#include "irq_user.h"
-+#include "os.h"
-+
-+struct irq_fd {
-+ struct irq_fd *next;
-+ void *id;
-+ int fd;
-+ int type;
-+ int irq;
-+ int pid;
-+ int events;
-+ int current_events;
-+ int freed;
-+};
-+
-+static struct irq_fd *active_fds = NULL;
-+static struct irq_fd **last_irq_ptr = &active_fds;
-+
-+static struct pollfd *pollfds = NULL;
-+static int pollfds_num = 0;
-+static int pollfds_size = 0;
-+
-+extern int io_count, intr_count;
-+
-+void sigio_handler(int sig, union uml_pt_regs *regs)
-+{
-+ struct irq_fd *irq_fd, *next;
-+ int i, n;
-+
-+ if(smp_sigio_handler()) return;
-+ while(1){
-+ n = poll(pollfds, pollfds_num, 0);
-+ if(n < 0){
-+ if(errno == EINTR) continue;
-+ printk("sigio_handler : poll returned %d, "
-+ "errno = %d\n", n, errno);
-+ break;
-+ }
-+ if(n == 0) break;
-+
-+ irq_fd = active_fds;
-+ for(i = 0; i < pollfds_num; i++){
-+ if(pollfds[i].revents != 0){
-+ irq_fd->current_events = pollfds[i].revents;
-+ pollfds[i].fd = -1;
-+ }
-+ irq_fd = irq_fd->next;
-+ }
-+
-+ for(irq_fd = active_fds; irq_fd != NULL; irq_fd = next){
-+ next = irq_fd->next;
-+ if(irq_fd->current_events != 0){
-+ irq_fd->current_events = 0;
-+ do_IRQ(irq_fd->irq, regs);
-+
-+ /* This is here because the next irq may be
-+ * freed in the handler. If a console goes
-+ * away, both the read and write irqs will be
-+ * freed. After do_IRQ, ->next will point to
-+ * a good IRQ.
-+ * Irqs can't be freed inside their handlers,
-+ * so the next best thing is to have them
-+ * marked as needing freeing, so that they
-+ * can be freed here.
-+ */
-+ next = irq_fd->next;
-+ if(irq_fd->freed)
-+ free_irq(irq_fd->irq, irq_fd->id);
-+ }
-+ }
-+ }
-+}
-+
-+int activate_ipi(int fd, int pid)
-+{
-+ return(os_set_fd_async(fd, pid));
-+}
-+
-+static void maybe_sigio_broken(int fd, int type)
-+{
-+ if(isatty(fd)){
-+ if((type == IRQ_WRITE) && !pty_output_sigio){
-+ write_sigio_workaround();
-+ add_sigio_fd(fd, 0);
-+ }
-+ else if((type == IRQ_READ) && !pty_close_sigio){
-+ write_sigio_workaround();
-+ add_sigio_fd(fd, 1);
-+ }
-+ }
-+}
-+
-+int activate_fd(int irq, int fd, int type, void *dev_id)
-+{
-+ struct pollfd *tmp_pfd;
-+ struct irq_fd *new_fd, *irq_fd;
-+ unsigned long flags;
-+ int pid, events, err, n, size;
-+
-+ pid = os_getpid();
-+ err = os_set_fd_async(fd, pid);
-+ if(err < 0)
-+ goto out;
-+
-+ new_fd = um_kmalloc(sizeof(*new_fd));
-+ err = -ENOMEM;
-+ if(new_fd == NULL)
-+ goto out;
-+
-+ if(type == IRQ_READ) events = POLLIN | POLLPRI;
-+ else events = POLLOUT;
-+ *new_fd = ((struct irq_fd) { .next = NULL,
-+ .id = dev_id,
-+ .fd = fd,
-+ .type = type,
-+ .irq = irq,
-+ .pid = pid,
-+ .events = events,
-+ .current_events = 0,
-+ .freed = 0 } );
-+
-+ /* Critical section - locked by a spinlock because this stuff can
-+ * be changed from interrupt handlers. The stuff above is done
-+ * outside the lock because it allocates memory.
-+ */
-+
-+ /* Actually, it only looks like it can be called from interrupt
-+ * context. The culprit is reactivate_fd, which calls
-+ * maybe_sigio_broken, which calls write_sigio_workaround,
-+ * which calls activate_fd. However, write_sigio_workaround should
-+ * only be called once, at boot time. That would make it clear that
-+ * this is called only from process context, and can be locked with
-+ * a semaphore.
-+ */
-+ flags = irq_lock();
-+ for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
-+ if((irq_fd->fd == fd) && (irq_fd->type == type)){
-+ printk("Registering fd %d twice\n", fd);
-+ printk("Irqs : %d, %d\n", irq_fd->irq, irq);
-+ printk("Ids : 0x%x, 0x%x\n", irq_fd->id, dev_id);
-+ goto out_unlock;
-+ }
-+ }
-+
-+ n = pollfds_num;
-+ if(n == pollfds_size){
-+ while(1){
-+ /* Here we have to drop the lock in order to call
-+ * kmalloc, which might sleep. If something else
-+ * came in and changed the pollfds array, we free
-+ * the buffer and try again.
-+ */
-+ irq_unlock(flags);
-+ size = (pollfds_num + 1) * sizeof(pollfds[0]);
-+ tmp_pfd = um_kmalloc(size);
-+ flags = irq_lock();
-+ if(tmp_pfd == NULL)
-+ goto out_unlock;
-+ if(n == pollfds_size)
-+ break;
-+ kfree(tmp_pfd);
-+ }
-+ if(pollfds != NULL){
-+ memcpy(tmp_pfd, pollfds,
-+ sizeof(pollfds[0]) * pollfds_size);
-+ kfree(pollfds);
-+ }
-+ pollfds = tmp_pfd;
-+ pollfds_size++;
-+ }
-+
-+ if(type == IRQ_WRITE)
-+ fd = -1;
-+
-+ pollfds[pollfds_num] = ((struct pollfd) { .fd = fd,
-+ .events = events,
-+ .revents = 0 });
-+ pollfds_num++;
-+
-+ *last_irq_ptr = new_fd;
-+ last_irq_ptr = &new_fd->next;
-+
-+ irq_unlock(flags);
-+
-+ /* This calls activate_fd, so it has to be outside the critical
-+ * section.
-+ */
-+ maybe_sigio_broken(fd, type);
-+
-+ return(0);
-+
-+ out_unlock:
-+ irq_unlock(flags);
-+ kfree(new_fd);
-+ out:
-+ return(err);
-+}
-+
-+static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
-+{
-+ struct irq_fd **prev;
-+ unsigned long flags;
-+ int i = 0;
-+
-+ flags = irq_lock();
-+ prev = &active_fds;
-+ while(*prev != NULL){
-+ if((*test)(*prev, arg)){
-+ struct irq_fd *old_fd = *prev;
-+ if((pollfds[i].fd != -1) &&
-+ (pollfds[i].fd != (*prev)->fd)){
-+ printk("free_irq_by_cb - mismatch between "
-+ "active_fds and pollfds, fd %d vs %d\n",
-+ (*prev)->fd, pollfds[i].fd);
-+ goto out;
-+ }
-+ memcpy(&pollfds[i], &pollfds[i + 1],
-+ (pollfds_num - i - 1) * sizeof(pollfds[0]));
-+ pollfds_num--;
-+ if(last_irq_ptr == &old_fd->next)
-+ last_irq_ptr = prev;
-+ *prev = (*prev)->next;
-+ if(old_fd->type == IRQ_WRITE)
-+ ignore_sigio_fd(old_fd->fd);
-+ kfree(old_fd);
-+ continue;
-+ }
-+ prev = &(*prev)->next;
-+ i++;
-+ }
-+ out:
-+ irq_unlock(flags);
-+}
-+
-+struct irq_and_dev {
-+ int irq;
-+ void *dev;
-+};
-+
-+static int same_irq_and_dev(struct irq_fd *irq, void *d)
-+{
-+ struct irq_and_dev *data = d;
-+
-+ return((irq->irq == data->irq) && (irq->id == data->dev));
-+}
-+
-+void free_irq_by_irq_and_dev(int irq, void *dev)
-+{
-+ struct irq_and_dev data = ((struct irq_and_dev) { .irq = irq,
-+ .dev = dev });
-+
-+ free_irq_by_cb(same_irq_and_dev, &data);
-+}
-+
-+static int same_fd(struct irq_fd *irq, void *fd)
-+{
-+ return(irq->fd == *((int *) fd));
-+}
-+
-+void free_irq_by_fd(int fd)
-+{
-+ free_irq_by_cb(same_fd, &fd);
-+}
-+
-+static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
-+{
-+ struct irq_fd *irq;
-+ int i = 0;
-+
-+ for(irq=active_fds; irq != NULL; irq = irq->next){
-+ if((irq->fd == fd) && (irq->irq == irqnum)) break;
-+ i++;
-+ }
-+ if(irq == NULL){
-+ printk("find_irq_by_fd doesn't have descriptor %d\n", fd);
-+ goto out;
-+ }
-+ if((pollfds[i].fd != -1) && (pollfds[i].fd != fd)){
-+ printk("find_irq_by_fd - mismatch between active_fds and "
-+ "pollfds, fd %d vs %d, need %d\n", irq->fd,
-+ pollfds[i].fd, fd);
-+ irq = NULL;
-+ goto out;
-+ }
-+ *index_out = i;
-+ out:
-+ return(irq);
-+}
-+
-+void free_irq_later(int irq, void *dev_id)
-+{
-+ struct irq_fd *irq_fd;
-+ unsigned long flags;
-+
-+ flags = irq_lock();
-+ for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
-+ if((irq_fd->irq == irq) && (irq_fd->id == dev_id))
-+ break;
-+ }
-+ if(irq_fd == NULL){
-+ printk("free_irq_later found no irq, irq = %d, "
-+ "dev_id = 0x%p\n", irq, dev_id);
-+ goto out;
-+ }
-+ irq_fd->freed = 1;
-+ out:
-+ irq_unlock(flags);
-+}
-+
-+void reactivate_fd(int fd, int irqnum)
-+{
-+ struct irq_fd *irq;
-+ unsigned long flags;
-+ int i;
-+
-+ flags = irq_lock();
-+ irq = find_irq_by_fd(fd, irqnum, &i);
-+ if(irq == NULL){
-+ irq_unlock(flags);
-+ return;
-+ }
-+
-+ pollfds[i].fd = irq->fd;
-+
-+ irq_unlock(flags);
-+
-+ /* This calls activate_fd, so it has to be outside the critical
-+ * section.
-+ */
-+ maybe_sigio_broken(fd, irq->type);
-+}
-+
-+void deactivate_fd(int fd, int irqnum)
-+{
-+ struct irq_fd *irq;
-+ unsigned long flags;
-+ int i;
-+
-+ flags = irq_lock();
-+ irq = find_irq_by_fd(fd, irqnum, &i);
-+ if(irq == NULL)
-+ goto out;
-+ pollfds[i].fd = -1;
-+ out:
-+ irq_unlock(flags);
-+}
-+
-+void forward_ipi(int fd, int pid)
-+{
-+ int err;
-+
-+ err = os_set_owner(fd, pid);
-+ if(err < 0)
-+ printk("forward_ipi: set_owner failed, fd = %d, me = %d, "
-+ "target = %d, err = %d\n", fd, os_getpid(), pid, -err);
-+}
-+
-+void forward_interrupts(int pid)
-+{
-+ struct irq_fd *irq;
-+ unsigned long flags;
-+ int err;
-+
-+ flags = irq_lock();
-+ for(irq=active_fds;irq != NULL;irq = irq->next){
-+ err = os_set_owner(irq->fd, pid);
-+ if(err < 0){
-+ /* XXX Just remove the irq rather than
-+ * print out an infinite stream of these
-+ */
-+ printk("Failed to forward %d to pid %d, err = %d\n",
-+ irq->fd, pid, -err);
-+ }
-+
-+ irq->pid = pid;
-+ }
-+ irq_unlock(flags);
-+}
-+
-+void init_irq_signals(int on_sigstack)
-+{
-+ __sighandler_t h;
-+ int flags;
-+
-+ flags = on_sigstack ? SA_ONSTACK : 0;
-+ if(timer_irq_inited) h = (__sighandler_t) alarm_handler;
-+ else h = boot_timer_handler;
-+
-+ set_handler(SIGVTALRM, h, flags | SA_RESTART,
-+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1);
-+ set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART,
-+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
-+ signal(SIGWINCH, SIG_IGN);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/ksyms.c um/arch/um/kernel/ksyms.c
---- orig/arch/um/kernel/ksyms.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/ksyms.c 2004-01-23 00:44:09.000000000 -0500
-@@ -0,0 +1,120 @@
-+/*
-+ * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/config.h"
-+#include "linux/module.h"
-+#include "linux/string.h"
-+#include "linux/smp_lock.h"
-+#include "linux/spinlock.h"
-+#include "asm/current.h"
-+#include "asm/delay.h"
-+#include "asm/processor.h"
-+#include "asm/unistd.h"
-+#include "asm/pgalloc.h"
-+#include "asm/pgtable.h"
-+#include "asm/page.h"
-+#include "kern_util.h"
-+#include "user_util.h"
-+#include "os.h"
-+#include "helper.h"
-+
-+EXPORT_SYMBOL(stop);
-+EXPORT_SYMBOL(strtok);
-+EXPORT_SYMBOL(uml_physmem);
-+EXPORT_SYMBOL(set_signals);
-+EXPORT_SYMBOL(get_signals);
-+EXPORT_SYMBOL(kernel_thread);
-+EXPORT_SYMBOL(__const_udelay);
-+EXPORT_SYMBOL(__udelay);
-+EXPORT_SYMBOL(sys_waitpid);
-+EXPORT_SYMBOL(task_size);
-+EXPORT_SYMBOL(flush_tlb_range);
-+EXPORT_SYMBOL(host_task_size);
-+EXPORT_SYMBOL(arch_validate);
-+EXPORT_SYMBOL(get_kmem_end);
-+
-+EXPORT_SYMBOL(high_physmem);
-+EXPORT_SYMBOL(empty_zero_page);
-+EXPORT_SYMBOL(um_virt_to_phys);
-+EXPORT_SYMBOL(__virt_to_page);
-+EXPORT_SYMBOL(to_phys);
-+EXPORT_SYMBOL(to_virt);
-+EXPORT_SYMBOL(mode_tt);
-+EXPORT_SYMBOL(handle_page_fault);
-+
-+#ifdef CONFIG_MODE_TT
-+EXPORT_SYMBOL(copy_from_user_tt);
-+EXPORT_SYMBOL(copy_to_user_tt);
-+#endif
-+
-+#ifdef CONFIG_MODE_SKAS
-+EXPORT_SYMBOL(copy_to_user_skas);
-+EXPORT_SYMBOL(copy_from_user_skas);
-+#endif
-+
-+EXPORT_SYMBOL(os_stat_fd);
-+EXPORT_SYMBOL(os_stat_file);
-+EXPORT_SYMBOL(os_access);
-+EXPORT_SYMBOL(os_print_error);
-+EXPORT_SYMBOL(os_get_exec_close);
-+EXPORT_SYMBOL(os_set_exec_close);
-+EXPORT_SYMBOL(os_getpid);
-+EXPORT_SYMBOL(os_open_file);
-+EXPORT_SYMBOL(os_read_file);
-+EXPORT_SYMBOL(os_write_file);
-+EXPORT_SYMBOL(os_seek_file);
-+EXPORT_SYMBOL(os_lock_file);
-+EXPORT_SYMBOL(os_pipe);
-+EXPORT_SYMBOL(os_file_type);
-+EXPORT_SYMBOL(os_file_mode);
-+EXPORT_SYMBOL(os_file_size);
-+EXPORT_SYMBOL(os_flush_stdout);
-+EXPORT_SYMBOL(os_close_file);
-+EXPORT_SYMBOL(os_set_fd_async);
-+EXPORT_SYMBOL(os_set_fd_block);
-+EXPORT_SYMBOL(helper_wait);
-+EXPORT_SYMBOL(os_shutdown_socket);
-+EXPORT_SYMBOL(os_create_unix_socket);
-+EXPORT_SYMBOL(os_connect_socket);
-+EXPORT_SYMBOL(os_accept_connection);
-+EXPORT_SYMBOL(os_ioctl_generic);
-+EXPORT_SYMBOL(os_rcv_fd);
-+EXPORT_SYMBOL(run_helper);
-+EXPORT_SYMBOL(start_thread);
-+EXPORT_SYMBOL(dump_thread);
-+
-+/* This is here because UML expands open to sys_open, not to a system
-+ * call instruction.
-+ */
-+EXPORT_SYMBOL(sys_open);
-+EXPORT_SYMBOL(sys_lseek);
-+EXPORT_SYMBOL(sys_read);
-+EXPORT_SYMBOL(sys_wait4);
-+
-+#ifdef CONFIG_SMP
-+
-+/* required for SMP */
-+
-+extern void FASTCALL( __write_lock_failed(rwlock_t *rw));
-+EXPORT_SYMBOL_NOVERS(__write_lock_failed);
-+
-+extern void FASTCALL( __read_lock_failed(rwlock_t *rw));
-+EXPORT_SYMBOL_NOVERS(__read_lock_failed);
-+
-+EXPORT_SYMBOL(kernel_flag_cacheline);
-+EXPORT_SYMBOL(smp_num_cpus);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/Makefile um/arch/um/kernel/Makefile
---- orig/arch/um/kernel/Makefile 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/Makefile 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,73 @@
-+#
-+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+# Licensed under the GPL
-+#
-+
-+O_TARGET = built-in.o
-+
-+obj-y = config.o checksum.o exec_kern.o exitcode.o frame_kern.o frame.o \
-+ helper.o init_task.o irq.o irq_user.o ksyms.o mem.o mem_user.o \
-+ physmem.o process.o process_kern.o ptrace.o reboot.o resource.o \
-+ sigio_user.o sigio_kern.o signal_kern.o signal_user.o smp.o \
-+ syscall_kern.o syscall_user.o sysrq.o sys_call_table.o tempfile.o \
-+ time.o time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o \
-+ um_arch.o umid.o user_syms.o user_util.o
-+
-+obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o
-+obj-$(CONFIG_GPROF) += gprof_syms.o
-+obj-$(CONFIG_GCOV) += gmon_syms.o
-+obj-$(CONFIG_TTY_LOG) += tty_log.o
-+
-+subdir-$(CONFIG_MODE_TT) += tt
-+subdir-$(CONFIG_MODE_SKAS) += skas
-+
-+user-objs-$(CONFIG_TTY_LOG) += tty_log.o
-+
-+obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
-+
-+# user_syms.o not included here because Rules.make has its own ideas about
-+# building anything in export-objs
-+
-+USER_OBJS = $(filter %_user.o,$(obj-y)) $(user-objs-y) config.o helper.o \
-+ process.o tempfile.o time.o umid.o user_util.o
-+
-+DMODULES-$(CONFIG_MODULES) = -D__CONFIG_MODULES__
-+DMODVERSIONS-$(CONFIG_MODVERSIONS) = -D__CONFIG_MODVERSIONS__
-+
-+export-objs-$(CONFIG_GPROF) += gprof_syms.o
-+export-objs-$(CONFIG_GCOV) += gmon_syms.o
-+
-+export-objs = ksyms.o process_kern.o signal_kern.o user_syms.o $(export-objs-y)
-+
-+CFLAGS_user_syms.o = -D__AUTOCONF_INCLUDED__ $(DMODULES-y) $(DMODVERSIONS-y) \
-+ -I/usr/include -I../include
-+
-+CFLAGS_frame.o := $(patsubst -fomit-frame-pointer,,$(USER_CFLAGS))
-+
-+include $(TOPDIR)/Rules.make
-+
-+$(USER_OBJS) : %.o: %.c
-+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $<
-+
-+# This has to be separate because it needs be compiled with frame pointers
-+# regardless of how the rest of the kernel is built.
-+
-+frame.o: frame.c
-+ $(CC) $(CFLAGS_$@) -c -o $@ $<
-+
-+QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; $$config =~ s/\n/\\n"\n"/g ; while(<STDIN>) { $$_ =~ s/CONFIG/$$config/; print $$_ }'
-+
-+config.c : config.c.in $(TOPDIR)/.config
-+ $(PERL) -e $(QUOTE) < config.c.in > $@
-+
-+clean:
-+ $(RM) config.c
-+ for dir in $(subdir-y) ; do $(MAKE) -C $$dir clean; done
-+
-+modules:
-+
-+fastdep:
-+
-+dep:
-+
-+archmrproper: clean
-diff -Naur -X ../exclude-files orig/arch/um/kernel/mem.c um/arch/um/kernel/mem.c
---- orig/arch/um/kernel/mem.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/mem.c 2003-12-22 01:25:00.000000000 -0500
-@@ -0,0 +1,336 @@
-+/*
-+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/stddef.h"
-+#include "linux/kernel.h"
-+#include "linux/mm.h"
-+#include "linux/bootmem.h"
-+#include "linux/highmem.h"
-+#include "asm/page.h"
-+#include "asm/fixmap.h"
-+#include "asm/pgalloc.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "kern.h"
-+#include "mem_user.h"
-+#include "uml_uaccess.h"
-+#include "os.h"
-+
-+extern char __binary_start;
-+
-+/* Changed during early boot */
-+unsigned long *empty_zero_page = NULL;
-+unsigned long *empty_bad_page = NULL;
-+pgd_t swapper_pg_dir[1024];
-+unsigned long highmem;
-+int kmalloc_ok = 0;
-+
-+static unsigned long brk_end;
-+static unsigned long totalram_pages = 0;
-+
-+void unmap_physmem(void)
-+{
-+ os_unmap_memory((void *) brk_end, uml_reserved - brk_end);
-+}
-+
-+static void map_cb(void *unused)
-+{
-+ map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
-+}
-+
-+#ifdef CONFIG_HIGHMEM
-+static void setup_highmem(unsigned long highmem_start,
-+ unsigned long highmem_len)
-+{
-+ struct page *page;
-+ unsigned long highmem_pfn;
-+ int i;
-+
-+ highmem_start_page = virt_to_page(highmem_start);
-+
-+ highmem_pfn = __pa(highmem_start) >> PAGE_SHIFT;
-+ for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){
-+ page = &mem_map[highmem_pfn + i];
-+ ClearPageReserved(page);
-+ set_bit(PG_highmem, &page->flags);
-+ atomic_set(&page->count, 1);
-+ __free_page(page);
-+ }
-+}
-+#endif
-+
-+void mem_init(void)
-+{
-+ unsigned long start;
-+
-+ /* clear the zero-page */
-+ memset((void *) empty_zero_page, 0, PAGE_SIZE);
-+
-+ /* Map in the area just after the brk now that kmalloc is about
-+ * to be turned on.
-+ */
-+ brk_end = (unsigned long) UML_ROUND_UP(sbrk(0));
-+ map_cb(NULL);
-+ initial_thread_cb(map_cb, NULL);
-+ free_bootmem(__pa(brk_end), uml_reserved - brk_end);
-+ uml_reserved = brk_end;
-+
-+ /* Fill in any hole at the start of the binary */
-+ start = (unsigned long) &__binary_start;
-+ if(uml_physmem != start){
-+ map_memory(uml_physmem, __pa(uml_physmem), start - uml_physmem,
-+ 1, 1, 0);
-+ }
-+
-+ /* this will put all low memory onto the freelists */
-+ totalram_pages = free_all_bootmem();
-+ totalram_pages += highmem >> PAGE_SHIFT;
-+ num_physpages = totalram_pages;
-+ printk(KERN_INFO "Memory: %luk available\n",
-+ (unsigned long) nr_free_pages() << (PAGE_SHIFT-10));
-+ kmalloc_ok = 1;
-+
-+#ifdef CONFIG_HIGHMEM
-+ setup_highmem(end_iomem, highmem);
-+#endif
-+}
-+
-+static void __init fixrange_init(unsigned long start, unsigned long end,
-+ pgd_t *pgd_base)
-+{
-+ pgd_t *pgd;
-+ pmd_t *pmd;
-+ pte_t *pte;
-+ int i, j;
-+ unsigned long vaddr;
-+
-+ vaddr = start;
-+ i = __pgd_offset(vaddr);
-+ j = __pmd_offset(vaddr);
-+ pgd = pgd_base + i;
-+
-+ for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) {
-+ pmd = (pmd_t *)pgd;
-+ for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
-+ if (pmd_none(*pmd)) {
-+ pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-+ set_pmd(pmd, __pmd(_KERNPG_TABLE +
-+ (unsigned long) __pa(pte)));
-+ if (pte != pte_offset(pmd, 0))
-+ BUG();
-+ }
-+ vaddr += PMD_SIZE;
-+ }
-+ j = 0;
-+ }
-+}
-+
-+#ifdef CONFIG_HIGHMEM
-+pte_t *kmap_pte;
-+pgprot_t kmap_prot;
-+
-+#define kmap_get_fixmap_pte(vaddr) \
-+ pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
-+
-+void __init kmap_init(void)
-+{
-+ unsigned long kmap_vstart;
-+
-+ /* cache the first kmap pte */
-+ kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
-+ kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
-+
-+ kmap_prot = PAGE_KERNEL;
-+}
-+
-+static void init_highmem(void)
-+{
-+ pgd_t *pgd;
-+ pmd_t *pmd;
-+ pte_t *pte;
-+ unsigned long vaddr;
-+
-+ /*
-+ * Permanent kmaps:
-+ */
-+ vaddr = PKMAP_BASE;
-+ fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, swapper_pg_dir);
-+
-+ pgd = swapper_pg_dir + __pgd_offset(vaddr);
-+ pmd = pmd_offset(pgd, vaddr);
-+ pte = pte_offset(pmd, vaddr);
-+ pkmap_page_table = pte;
-+
-+ kmap_init();
-+}
-+
-+#endif /* CONFIG_HIGHMEM */
-+
-+void paging_init(void)
-+{
-+ unsigned long zones_size[MAX_NR_ZONES], vaddr;
-+ int i;
-+
-+ empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
-+ empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
-+ for(i=0;i<sizeof(zones_size)/sizeof(zones_size[0]);i++)
-+ zones_size[i] = 0;
-+ zones_size[0] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT);
-+ zones_size[2] = highmem >> PAGE_SHIFT;
-+ free_area_init(zones_size);
-+
-+ /*
-+ * Fixed mappings, only the page table structure has to be
-+ * created - mappings will be set by set_fixmap():
-+ */
-+ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
-+ fixrange_init(vaddr, FIXADDR_TOP, swapper_pg_dir);
-+
-+#if CONFIG_HIGHMEM
-+ init_highmem();
-+#endif
-+}
-+
-+struct page *arch_validate(struct page *page, int mask, int order)
-+{
-+ unsigned long addr, zero = 0;
-+ int i;
-+
-+ again:
-+ if(page == NULL) return(page);
-+ if(PageHighMem(page)) return(page);
-+
-+ addr = (unsigned long) page_address(page);
-+ for(i = 0; i < (1 << order); i++){
-+ current->thread.fault_addr = (void *) addr;
-+ if(__do_copy_to_user((void *) addr, &zero,
-+ sizeof(zero),
-+ ¤t->thread.fault_addr,
-+ ¤t->thread.fault_catcher)){
-+ if(!(mask & __GFP_WAIT)) return(NULL);
-+ else break;
-+ }
-+ addr += PAGE_SIZE;
-+ }
-+ if(i == (1 << order)) return(page);
-+ page = _alloc_pages(mask, order);
-+ goto again;
-+}
-+
-+/* This can't do anything because nothing in the kernel image can be freed
-+ * since it's not in kernel physical memory.
-+ */
-+
-+void free_initmem(void)
-+{
-+}
-+
-+#ifdef CONFIG_BLK_DEV_INITRD
-+
-+void free_initrd_mem(unsigned long start, unsigned long end)
-+{
-+ if (start < end)
-+ printk ("Freeing initrd memory: %ldk freed\n",
-+ (end - start) >> 10);
-+ for (; start < end; start += PAGE_SIZE) {
-+ ClearPageReserved(virt_to_page(start));
-+ set_page_count(virt_to_page(start), 1);
-+ free_page(start);
-+ totalram_pages++;
-+ }
-+}
-+
-+#endif
-+
-+int do_check_pgt_cache(int low, int high)
-+{
-+ int freed = 0;
-+ if(pgtable_cache_size > high) {
-+ do {
-+ if (pgd_quicklist) {
-+ free_pgd_slow(get_pgd_fast());
-+ freed++;
-+ }
-+ if (pmd_quicklist) {
-+ pmd_free_slow(pmd_alloc_one_fast(NULL, 0));
-+ freed++;
-+ }
-+ if (pte_quicklist) {
-+ pte_free_slow(pte_alloc_one_fast(NULL, 0));
-+ freed++;
-+ }
-+ } while(pgtable_cache_size > low);
-+ }
-+ return freed;
-+}
-+
-+void show_mem(void)
-+{
-+ int i, total = 0, reserved = 0;
-+ int shared = 0, cached = 0;
-+ int highmem = 0;
-+
-+ printk("Mem-info:\n");
-+ show_free_areas();
-+ printk("Free swap: %6dkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
-+ i = max_mapnr;
-+ while(i-- > 0) {
-+ total++;
-+ if(PageHighMem(mem_map + i))
-+ highmem++;
-+ if(PageReserved(mem_map + i))
-+ reserved++;
-+ else if(PageSwapCache(mem_map + i))
-+ cached++;
-+ else if(page_count(mem_map + i))
-+ shared += page_count(mem_map + i) - 1;
-+ }
-+ printk("%d pages of RAM\n", total);
-+ printk("%d pages of HIGHMEM\n", highmem);
-+ printk("%d reserved pages\n", reserved);
-+ printk("%d pages shared\n", shared);
-+ printk("%d pages swap cached\n", cached);
-+ printk("%ld pages in page table cache\n", pgtable_cache_size);
-+ show_buffers();
-+}
-+
-+/* Changed by meminfo_compat, which is a setup */
-+static int meminfo_22 = 0;
-+
-+static int meminfo_compat(char *str)
-+{
-+ meminfo_22 = 1;
-+ return(1);
-+}
-+
-+__setup("22_meminfo", meminfo_compat);
-+
-+void si_meminfo(struct sysinfo *val)
-+{
-+ val->totalram = totalram_pages;
-+ val->sharedram = 0;
-+ val->freeram = nr_free_pages();
-+ val->bufferram = atomic_read(&buffermem_pages);
-+ val->totalhigh = highmem >> PAGE_SHIFT;
-+ val->freehigh = nr_free_highpages();
-+ val->mem_unit = PAGE_SIZE;
-+ if(meminfo_22){
-+ val->freeram <<= PAGE_SHIFT;
-+ val->bufferram <<= PAGE_SHIFT;
-+ val->totalram <<= PAGE_SHIFT;
-+ val->sharedram <<= PAGE_SHIFT;
-+ }
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/mem_user.c um/arch/um/kernel/mem_user.c
---- orig/arch/um/kernel/mem_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/mem_user.c 2004-01-10 00:19:09.000000000 -0500
-@@ -0,0 +1,216 @@
-+/*
-+ * arch/um/kernel/mem_user.c
-+ *
-+ * BRIEF MODULE DESCRIPTION
-+ * user side memory routines for supporting IO memory inside user mode linux
-+ *
-+ * Copyright (C) 2001 RidgeRun, Inc.
-+ * Author: RidgeRun, Inc.
-+ * Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the
-+ * Free Software Foundation; either version 2 of the License, or (at your
-+ * option) any later version.
-+ *
-+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
-+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
-+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ *
-+ * 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.,
-+ * 675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <stddef.h>
-+#include <stdarg.h>
-+#include <unistd.h>
-+#include <errno.h>
-+#include <string.h>
-+#include <fcntl.h>
-+#include <sys/types.h>
-+#include <sys/mman.h>
-+#include "kern_util.h"
-+#include "user.h"
-+#include "user_util.h"
-+#include "mem_user.h"
-+#include "init.h"
-+#include "os.h"
-+#include "tempfile.h"
-+#include "kern_constants.h"
-+
-+extern struct mem_region physmem_region;
-+
-+#define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
-+
-+static int create_tmp_file(unsigned long len)
-+{
-+ int fd, err;
-+ char zero;
-+
-+ fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1);
-+ if(fd < 0) {
-+ os_print_error(fd, "make_tempfile");
-+ exit(1);
-+ }
-+
-+ err = os_mode_fd(fd, 0777);
-+ if(err < 0){
-+ os_print_error(err, "os_mode_fd");
-+ exit(1);
-+ }
-+ err = os_seek_file(fd, len);
-+ if(err < 0){
-+ os_print_error(err, "os_seek_file");
-+ exit(1);
-+ }
-+ zero = 0;
-+ err = os_write_file(fd, &zero, 1);
-+ if(err != 1){
-+ os_print_error(err, "os_write_file");
-+ exit(1);
-+ }
-+
-+ return(fd);
-+}
-+
-+static int have_devanon(void)
-+{
-+ int fd;
-+
-+ printk("Checking for /dev/anon on the host...");
-+ fd = open("/dev/anon", O_RDWR);
-+ if(fd < 0){
-+ printk("Not available (open failed with errno %d)\n", errno);
-+ return(0);
-+ }
-+
-+ printk("OK\n");
-+ return(1);
-+}
-+
-+static int create_anon_file(unsigned long len)
-+{
-+ void *addr;
-+ int fd;
-+
-+ fd = open("/dev/anon", O_RDWR);
-+ if(fd < 0) {
-+ os_print_error(fd, "opening /dev/anon");
-+ exit(1);
-+ }
-+
-+ addr = mmap(NULL, len, PROT_READ | PROT_WRITE , MAP_PRIVATE, fd, 0);
-+ if(addr == MAP_FAILED){
-+ os_print_error((int) addr, "mapping physmem file");
-+ exit(1);
-+ }
-+ munmap(addr, len);
-+
-+ return(fd);
-+}
-+
-+int create_mem_file(unsigned long len)
-+{
-+ int err, fd;
-+
-+ if(have_devanon())
-+ fd = create_anon_file(len);
-+ else fd = create_tmp_file(len);
-+
-+ err = os_set_exec_close(fd, 1);
-+ if(err < 0)
-+ os_print_error(err, "exec_close");
-+ return(fd);
-+}
-+
-+struct iomem_region *iomem_regions = NULL;
-+int iomem_size = 0;
-+
-+static int __init parse_iomem(char *str, int *add)
-+{
-+ struct iomem_region *new;
-+ struct uml_stat buf;
-+ char *file, *driver;
-+ int fd, err;
-+
-+ driver = str;
-+ file = strchr(str,',');
-+ if(file == NULL){
-+ printf("parse_iomem : failed to parse iomem\n");
-+ goto out;
-+ }
-+ *file = '\0';
-+ file++;
-+ fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0);
-+ if(fd < 0){
-+ os_print_error(fd, "parse_iomem - Couldn't open io file");
-+ goto out;
-+ }
-+
-+ err = os_stat_fd(fd, &buf);
-+ if(err < 0){
-+ os_print_error(err, "parse_iomem - cannot stat_fd file");
-+ goto out_close;
-+ }
-+
-+ new = malloc(sizeof(*new));
-+ if(new == NULL){
-+ perror("Couldn't allocate iomem_region struct");
-+ goto out_close;
-+ }
-+
-+ *new = ((struct iomem_region) { .next = iomem_regions,
-+ .driver = driver,
-+ .fd = fd,
-+ .size = buf.ust_size,
-+ .phys = 0,
-+ .virt = 0 });
-+ iomem_regions = new;
-+ iomem_size += new->size + UM_KERN_PAGE_SIZE;
-+
-+ return(0);
-+ out_close:
-+ os_close_file(fd);
-+ out:
-+ return(1);
-+}
-+
-+__uml_setup("iomem=", parse_iomem,
-+"iomem=<name>,<file>\n"
-+" Configure <file> as an IO memory region named <name>.\n\n"
-+);
-+
-+int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x,
-+ int must_succeed)
-+{
-+ int err;
-+
-+ err = os_protect_memory((void *) addr, len, r, w, x);
-+ if(err < 0){
-+ if(must_succeed)
-+ panic("protect failed, err = %d", -err);
-+ else return(err);
-+ }
-+ return(0);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/mprot.h um/arch/um/kernel/mprot.h
---- orig/arch/um/kernel/mprot.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/mprot.h 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __MPROT_H__
-+#define __MPROT_H__
-+
-+extern void no_access(unsigned long addr, unsigned int len);
-+
-+#endif
-diff -Naur -X ../exclude-files orig/arch/um/kernel/physmem.c um/arch/um/kernel/physmem.c
---- orig/arch/um/kernel/physmem.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/physmem.c 2004-01-16 23:38:02.000000000 -0500
-@@ -0,0 +1,446 @@
-+/*
-+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/mm.h"
-+#include "linux/ghash.h"
-+#include "linux/slab.h"
-+#include "linux/vmalloc.h"
-+#include "linux/bootmem.h"
-+#include "asm/types.h"
-+#include "asm/pgtable.h"
-+#include "kern_util.h"
-+#include "user_util.h"
-+#include "mode_kern.h"
-+#include "mem.h"
-+#include "mem_user.h"
-+#include "os.h"
-+#include "kern.h"
-+#include "init.h"
-+
-+#define PHYS_HASHSIZE (8192)
-+
-+struct phys_desc;
-+
-+DEF_HASH_STRUCTS(virtmem, PHYS_HASHSIZE, struct phys_desc);
-+
-+struct phys_desc {
-+ struct virtmem_ptrs virt_ptrs;
-+ int fd;
-+ __u64 offset;
-+ void *virt;
-+ unsigned long phys;
-+ struct list_head list;
-+};
-+
-+struct virtmem_table virtmem_hash;
-+
-+static int virt_cmp(void *virt1, void *virt2)
-+{
-+ return(virt1 != virt2);
-+}
-+
-+static int virt_hash(void *virt)
-+{
-+ unsigned long addr = ((unsigned long) virt) >> PAGE_SHIFT;
-+ return(addr % PHYS_HASHSIZE);
-+}
-+
-+DEF_HASH(static, virtmem, struct phys_desc, virt_ptrs, void *, virt, virt_cmp,
-+ virt_hash);
-+
-+LIST_HEAD(descriptor_mappings);
-+
-+struct desc_mapping {
-+ int fd;
-+ struct list_head list;
-+ struct list_head pages;
-+};
-+
-+static struct desc_mapping *find_mapping(int fd)
-+{
-+ struct desc_mapping *desc;
-+ struct list_head *ele;
-+
-+ list_for_each(ele, &descriptor_mappings){
-+ desc = list_entry(ele, struct desc_mapping, list);
-+ if(desc->fd == fd)
-+ return(desc);
-+ }
-+
-+ return(NULL);
-+}
-+
-+static struct desc_mapping *descriptor_mapping(int fd)
-+{
-+ struct desc_mapping *desc;
-+
-+ desc = find_mapping(fd);
-+ if(desc != NULL)
-+ return(desc);
-+
-+ desc = kmalloc(sizeof(*desc), GFP_ATOMIC);
-+ if(desc == NULL)
-+ return(NULL);
-+
-+ *desc = ((struct desc_mapping)
-+ { .fd = fd,
-+ .list = LIST_HEAD_INIT(desc->list),
-+ .pages = LIST_HEAD_INIT(desc->pages) });
-+ list_add(&desc->list, &descriptor_mappings);
-+
-+ return(desc);
-+}
-+
-+int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w)
-+{
-+ struct desc_mapping *fd_maps;
-+ struct phys_desc *desc;
-+ unsigned long phys;
-+ int err;
-+
-+ fd_maps = descriptor_mapping(fd);
-+ if(fd_maps == NULL)
-+ return(-ENOMEM);
-+
-+ phys = __pa(virt);
-+ if(find_virtmem_hash(&virtmem_hash, virt) != NULL)
-+ panic("Address 0x%p is already substituted\n", virt);
-+
-+ err = -ENOMEM;
-+ desc = kmalloc(sizeof(*desc), GFP_ATOMIC);
-+ if(desc == NULL)
-+ goto out;
-+
-+ *desc = ((struct phys_desc)
-+ { .virt_ptrs = { NULL, NULL },
-+ .fd = fd,
-+ .offset = offset,
-+ .virt = virt,
-+ .phys = __pa(virt),
-+ .list = LIST_HEAD_INIT(desc->list) });
-+ insert_virtmem_hash(&virtmem_hash, desc);
-+
-+ list_add(&desc->list, &fd_maps->pages);
-+
-+ virt = (void *) ((unsigned long) virt & PAGE_MASK);
-+ err = os_map_memory(virt, fd, offset, PAGE_SIZE, 1, w, 0);
-+ if(!err)
-+ goto out;
-+
-+ remove_virtmem_hash(&virtmem_hash, desc);
-+ kfree(desc);
-+ out:
-+ return(err);
-+}
-+
-+static int physmem_fd = -1;
-+
-+static void remove_mapping(struct phys_desc *desc)
-+{
-+ void *virt = desc->virt;
-+ int err;
-+
-+ remove_virtmem_hash(&virtmem_hash, desc);
-+ list_del(&desc->list);
-+ kfree(desc);
-+
-+ err = os_map_memory(virt, physmem_fd, __pa(virt), PAGE_SIZE, 1, 1, 0);
-+ if(err)
-+ panic("Failed to unmap block device page from physical memory, "
-+ "errno = %d", -err);
-+}
-+
-+int physmem_remove_mapping(void *virt)
-+{
-+ struct phys_desc *desc;
-+
-+ virt = (void *) ((unsigned long) virt & PAGE_MASK);
-+ desc = find_virtmem_hash(&virtmem_hash, virt);
-+ if(desc == NULL)
-+ return(0);
-+
-+ remove_mapping(desc);
-+ return(1);
-+}
-+
-+void physmem_forget_descriptor(int fd)
-+{
-+ struct desc_mapping *desc;
-+ struct phys_desc *page;
-+ struct list_head *ele, *next;
-+ __u64 offset;
-+ void *addr;
-+ int err;
-+
-+ desc = find_mapping(fd);
-+ if(desc == NULL)
-+ return;
-+
-+ list_for_each_safe(ele, next, &desc->pages){
-+ page = list_entry(ele, struct phys_desc, list);
-+ offset = page->offset;
-+ addr = page->virt;
-+ remove_mapping(page);
-+ err = os_seek_file(fd, offset);
-+ if(err)
-+ panic("physmem_forget_descriptor - failed to seek "
-+ "to %lld in fd %d, error = %d\n",
-+ offset, fd, -err);
-+ err = os_read_file(fd, addr, PAGE_SIZE);
-+ if(err < 0)
-+ panic("physmem_forget_descriptor - failed to read "
-+ "from fd %d to 0x%p, error = %d\n",
-+ fd, addr, -err);
-+ }
-+
-+ list_del(&desc->list);
-+ kfree(desc);
-+}
-+
-+void arch_free_page(struct page *page, int order)
-+{
-+ void *virt;
-+ int i;
-+
-+ for(i = 0; i < (1 << order); i++){
-+ virt = __va(page_to_phys(page + i));
-+ physmem_remove_mapping(virt);
-+ }
-+}
-+
-+int is_remapped(void *virt)
-+{
-+ return(find_virtmem_hash(&virtmem_hash, virt) != NULL);
-+}
-+
-+/* Changed during early boot */
-+unsigned long high_physmem;
-+
-+extern unsigned long physmem_size;
-+
-+void *to_virt(unsigned long phys)
-+{
-+ return((void *) uml_physmem + phys);
-+}
-+
-+unsigned long to_phys(void *virt)
-+{
-+ return(((unsigned long) virt) - uml_physmem);
-+}
-+
-+int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem)
-+{
-+ struct page *p, *map;
-+ unsigned long phys_len, phys_pages, highmem_len, highmem_pages;
-+ unsigned long iomem_len, iomem_pages, total_len, total_pages;
-+ int i;
-+
-+ phys_pages = physmem >> PAGE_SHIFT;
-+ phys_len = phys_pages * sizeof(struct page);
-+
-+ iomem_pages = iomem >> PAGE_SHIFT;
-+ iomem_len = iomem_pages * sizeof(struct page);
-+
-+ highmem_pages = highmem >> PAGE_SHIFT;
-+ highmem_len = highmem_pages * sizeof(struct page);
-+
-+ total_pages = phys_pages + iomem_pages + highmem_pages;
-+ total_len = phys_len + iomem_pages + highmem_len;
-+
-+ if(kmalloc_ok){
-+ map = kmalloc(total_len, GFP_KERNEL);
-+ if(map == NULL)
-+ map = vmalloc(total_len);
-+ }
-+ else map = alloc_bootmem_low_pages(total_len);
-+
-+ if(map == NULL)
-+ return(-ENOMEM);
-+
-+ for(i = 0; i < total_pages; i++){
-+ p = &map[i];
-+ set_page_count(p, 0);
-+ SetPageReserved(p);
-+ INIT_LIST_HEAD(&p->list);
-+ }
-+
-+ mem_map = map;
-+ max_mapnr = total_pages;
-+ return(0);
-+}
-+
-+struct page *phys_to_page(const unsigned long phys)
-+{
-+ return(&mem_map[phys >> PAGE_SHIFT]);
-+}
-+
-+struct page *__virt_to_page(const unsigned long virt)
-+{
-+ return(&mem_map[__pa(virt) >> PAGE_SHIFT]);
-+}
-+
-+unsigned long page_to_phys(struct page *page)
-+{
-+ return((page - mem_map) << PAGE_SHIFT);
-+}
-+
-+pte_t mk_pte(struct page *page, pgprot_t pgprot)
-+{
-+ pte_t pte;
-+
-+ pte_val(pte) = page_to_phys(page) + pgprot_val(pgprot);
-+ if(pte_present(pte)) pte_mknewprot(pte_mknewpage(pte));
-+ return(pte);
-+}
-+
-+/* Changed during early boot */
-+static unsigned long kmem_top = 0;
-+
-+unsigned long get_kmem_end(void)
-+{
-+ if(kmem_top == 0)
-+ kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas);
-+ return(kmem_top);
-+}
-+
-+void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
-+ int r, int w, int x)
-+{
-+ __u64 offset;
-+ int fd, err;
-+
-+ fd = phys_mapping(phys, &offset);
-+ err = os_map_memory((void *) virt, fd, offset, len, r, w, x);
-+ if(err)
-+ panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, "
-+ "err = %d\n", virt, fd, offset, len, r, w, x, err);
-+}
-+
-+#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-+
-+void setup_physmem(unsigned long start, unsigned long reserve_end,
-+ unsigned long len, unsigned long highmem)
-+{
-+ unsigned long reserve = reserve_end - start;
-+ int pfn = PFN_UP(__pa(reserve_end));
-+ int delta = (len - reserve) >> PAGE_SHIFT;
-+ int err, offset, bootmap_size;
-+
-+ physmem_fd = create_mem_file(len + highmem);
-+
-+ offset = uml_reserved - uml_physmem;
-+ err = os_map_memory((void *) uml_reserved, physmem_fd, offset,
-+ len - offset, 1, 1, 0);
-+ if(err < 0){
-+ os_print_error(err, "Mapping memory");
-+ exit(1);
-+ }
-+
-+ bootmap_size = init_bootmem(pfn, pfn + delta);
-+ free_bootmem(__pa(reserve_end) + bootmap_size,
-+ len - bootmap_size - reserve);
-+}
-+
-+int phys_mapping(unsigned long phys, __u64 *offset_out)
-+{
-+ struct phys_desc *desc = find_virtmem_hash(&virtmem_hash,
-+ __va(phys & PAGE_MASK));
-+ int fd = -1;
-+
-+ if(desc != NULL){
-+ fd = desc->fd;
-+ *offset_out = desc->offset;
-+ }
-+ else if(phys < physmem_size){
-+ fd = physmem_fd;
-+ *offset_out = phys;
-+ }
-+ else if(phys < __pa(end_iomem)){
-+ struct iomem_region *region = iomem_regions;
-+
-+ while(region != NULL){
-+ if((phys >= region->phys) &&
-+ (phys < region->phys + region->size)){
-+ fd = region->fd;
-+ *offset_out = phys - region->phys;
-+ break;
-+ }
-+ region = region->next;
-+ }
-+ }
-+ else if(phys < __pa(end_iomem) + highmem){
-+ fd = physmem_fd;
-+ *offset_out = phys - iomem_size;
-+ }
-+
-+ return(fd);
-+}
-+
-+static int __init uml_mem_setup(char *line, int *add)
-+{
-+ char *retptr;
-+ physmem_size = memparse(line,&retptr);
-+ return 0;
-+}
-+__uml_setup("mem=", uml_mem_setup,
-+"mem=<Amount of desired ram>\n"
-+" This controls how much \"physical\" memory the kernel allocates\n"
-+" for the system. The size is specified as a number followed by\n"
-+" one of 'k', 'K', 'm', 'M', which have the obvious meanings.\n"
-+" This is not related to the amount of memory in the host. It can\n"
-+" be more, and the excess, if it's ever used, will just be swapped out.\n"
-+" Example: mem=64M\n\n"
-+);
-+
-+unsigned long find_iomem(char *driver, unsigned long *len_out)
-+{
-+ struct iomem_region *region = iomem_regions;
-+
-+ while(region != NULL){
-+ if(!strcmp(region->driver, driver)){
-+ *len_out = region->size;
-+ return(region->virt);
-+ }
-+ }
-+
-+ return(0);
-+}
-+
-+int setup_iomem(void)
-+{
-+ struct iomem_region *region = iomem_regions;
-+ unsigned long iomem_start = high_physmem + PAGE_SIZE;
-+ int err;
-+
-+ while(region != NULL){
-+ err = os_map_memory((void *) iomem_start, region->fd, 0,
-+ region->size, 1, 1, 0);
-+ if(err)
-+ printk("Mapping iomem region for driver '%s' failed, "
-+ "errno = %d\n", region->driver, -err);
-+ else {
-+ region->virt = iomem_start;
-+ region->phys = __pa(region->virt);
-+ }
-+
-+ iomem_start += region->size + PAGE_SIZE;
-+ region = region->next;
-+ }
-+
-+ return(0);
-+}
-+
-+__initcall(setup_iomem);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/process.c um/arch/um/kernel/process.c
---- orig/arch/um/kernel/process.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/process.c 2004-01-31 02:47:57.000000000 -0500
-@@ -0,0 +1,289 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdio.h>
-+#include <unistd.h>
-+#include <signal.h>
-+#include <sched.h>
-+#include <errno.h>
-+#include <stdarg.h>
-+#include <stdlib.h>
-+#include <setjmp.h>
-+#include <sys/time.h>
-+#include <sys/ptrace.h>
-+#include <sys/wait.h>
-+#include <sys/mman.h>
-+#include <asm/ptrace.h>
-+#include <asm/sigcontext.h>
-+#include <asm/unistd.h>
-+#include <asm/page.h>
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "user.h"
-+#include "process.h"
-+#include "signal_kern.h"
-+#include "signal_user.h"
-+#include "sysdep/ptrace.h"
-+#include "sysdep/sigcontext.h"
-+#include "irq_user.h"
-+#include "ptrace_user.h"
-+#include "time_user.h"
-+#include "init.h"
-+#include "os.h"
-+#include "uml-config.h"
-+#include "choose-mode.h"
-+#include "mode.h"
-+#ifdef UML_CONFIG_MODE_SKAS
-+#include "skas.h"
-+#include "skas_ptrace.h"
-+#endif
-+
-+void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
-+{
-+ int flags = 0, pages;
-+
-+ if(sig_stack != NULL){
-+ pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2;
-+ set_sigstack(sig_stack, pages * page_size());
-+ flags = SA_ONSTACK;
-+ }
-+ if(usr1_handler) set_handler(SIGUSR1, usr1_handler, flags, -1);
-+}
-+
-+void init_new_thread_signals(int altstack)
-+{
-+ int flags = altstack ? SA_ONSTACK : 0;
-+
-+ /* NODEFER is set here because SEGV isn't turned back on when the
-+ * handler is ready to receive signals. This causes any segfault
-+ * during a copy_user to kill the process because the fault is blocked.
-+ */
-+ set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags | SA_NODEFER,
-+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
-+ set_handler(SIGTRAP, (__sighandler_t) sig_handler, flags,
-+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
-+ set_handler(SIGFPE, (__sighandler_t) sig_handler, flags,
-+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
-+ set_handler(SIGILL, (__sighandler_t) sig_handler, flags,
-+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
-+ set_handler(SIGBUS, (__sighandler_t) sig_handler, flags,
-+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
-+ set_handler(SIGWINCH, (__sighandler_t) sig_handler, flags,
-+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
-+ set_handler(SIGUSR2, (__sighandler_t) sig_handler,
-+ SA_NOMASK | flags, -1);
-+ signal(SIGHUP, SIG_IGN);
-+
-+ init_irq_signals(altstack);
-+}
-+
-+struct tramp {
-+ int (*tramp)(void *);
-+ void *tramp_data;
-+ unsigned long temp_stack;
-+ int flags;
-+ int pid;
-+};
-+
-+/* See above for why sigkill is here */
-+
-+int sigkill = SIGKILL;
-+
-+int outer_tramp(void *arg)
-+{
-+ struct tramp *t;
-+ int sig = sigkill;
-+
-+ t = arg;
-+ t->pid = clone(t->tramp, (void *) t->temp_stack + page_size()/2,
-+ t->flags, t->tramp_data);
-+ if(t->pid > 0) wait_for_stop(t->pid, SIGSTOP, PTRACE_CONT, NULL);
-+ kill(os_getpid(), sig);
-+ _exit(0);
-+}
-+
-+int start_fork_tramp(void *thread_arg, unsigned long temp_stack,
-+ int clone_flags, int (*tramp)(void *))
-+{
-+ struct tramp arg;
-+ unsigned long sp;
-+ int new_pid, status, err;
-+
-+ /* The trampoline will run on the temporary stack */
-+ sp = stack_sp(temp_stack);
-+
-+ clone_flags |= CLONE_FILES | SIGCHLD;
-+
-+ arg.tramp = tramp;
-+ arg.tramp_data = thread_arg;
-+ arg.temp_stack = temp_stack;
-+ arg.flags = clone_flags;
-+
-+ /* Start the process and wait for it to kill itself */
-+ new_pid = clone(outer_tramp, (void *) sp, clone_flags, &arg);
-+ if(new_pid < 0) return(-errno);
-+ while(((err = waitpid(new_pid, &status, 0)) < 0) && (errno == EINTR)) ;
-+ if(err < 0) panic("Waiting for outer trampoline failed - errno = %d",
-+ errno);
-+ if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL))
-+ panic("outer trampoline didn't exit with SIGKILL, "
-+ "status = %d", status);
-+
-+ return(arg.pid);
-+}
-+
-+void suspend_new_thread(int fd)
-+{
-+ char c;
-+
-+ os_stop_process(os_getpid());
-+
-+ if(os_read_file(fd, &c, sizeof(c)) != sizeof(c))
-+ panic("read failed in suspend_new_thread");
-+}
-+
-+static int ptrace_child(void *arg)
-+{
-+ int pid = os_getpid();
-+
-+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){
-+ perror("ptrace");
-+ os_kill_process(pid, 0);
-+ }
-+ os_stop_process(pid);
-+ _exit(os_getpid() == pid);
-+}
-+
-+static int start_ptraced_child(void **stack_out)
-+{
-+ void *stack;
-+ unsigned long sp;
-+ int pid, n, status;
-+
-+ stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
-+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-+ if(stack == MAP_FAILED)
-+ panic("check_ptrace : mmap failed, errno = %d", errno);
-+ sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
-+ pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL);
-+ if(pid < 0)
-+ panic("check_ptrace : clone failed, errno = %d", errno);
-+ n = waitpid(pid, &status, WUNTRACED);
-+ if(n < 0)
-+ panic("check_ptrace : wait failed, errno = %d", errno);
-+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
-+ panic("check_ptrace : expected SIGSTOP, got status = %d",
-+ status);
-+
-+ *stack_out = stack;
-+ return(pid);
-+}
-+
-+static void stop_ptraced_child(int pid, void *stack, int exitcode)
-+{
-+ int status, n;
-+
-+ if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
-+ panic("check_ptrace : ptrace failed, errno = %d", errno);
-+ n = waitpid(pid, &status, 0);
-+ if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode))
-+ panic("check_ptrace : child exited with status 0x%x", status);
-+
-+ if(munmap(stack, PAGE_SIZE) < 0)
-+ panic("check_ptrace : munmap failed, errno = %d", errno);
-+}
-+
-+void __init check_ptrace(void)
-+{
-+ void *stack;
-+ int pid, syscall, n, status;
-+
-+ printk("Checking that ptrace can change system call numbers...");
-+ pid = start_ptraced_child(&stack);
-+
-+ while(1){
-+ if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
-+ panic("check_ptrace : ptrace failed, errno = %d",
-+ errno);
-+ n = waitpid(pid, &status, WUNTRACED);
-+ if(n < 0)
-+ panic("check_ptrace : wait failed, errno = %d", errno);
-+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
-+ panic("check_ptrace : expected SIGTRAP, "
-+ "got status = %d", status);
-+
-+ syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET,
-+ 0);
-+ if(syscall == __NR_getpid){
-+ n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
-+ __NR_getppid);
-+ if(n < 0)
-+ panic("check_ptrace : failed to modify system "
-+ "call, errno = %d", errno);
-+ break;
-+ }
-+ }
-+ stop_ptraced_child(pid, stack, 0);
-+ printk("OK\n");
-+}
-+
-+int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
-+{
-+ sigjmp_buf buf;
-+ int n;
-+
-+ *jmp_ptr = &buf;
-+ n = sigsetjmp(buf, 1);
-+ if(n != 0)
-+ return(n);
-+ (*fn)(arg);
-+ return(0);
-+}
-+
-+int can_do_skas(void)
-+{
-+#ifdef UML_CONFIG_MODE_SKAS
-+ struct ptrace_faultinfo fi;
-+ void *stack;
-+ int pid, n, ret = 1;
-+
-+ printf("Checking for the skas3 patch in the host...");
-+ pid = start_ptraced_child(&stack);
-+
-+ n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi);
-+ if(n < 0){
-+ if(errno == EIO)
-+ printf("not found\n");
-+ else printf("No (unexpected errno - %d)\n", errno);
-+ ret = 0;
-+ }
-+ else printf("found\n");
-+
-+ init_registers(pid);
-+ stop_ptraced_child(pid, stack, 1);
-+
-+ printf("Checking for /proc/mm...");
-+ if(os_access("/proc/mm", OS_ACC_W_OK) < 0){
-+ printf("not found\n");
-+ ret = 0;
-+ }
-+ else printf("found\n");
-+
-+ return(ret);
-+#else
-+ return(0);
-+#endif
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/process_kern.c um/arch/um/kernel/process_kern.c
---- orig/arch/um/kernel/process_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/process_kern.c 2003-11-08 08:37:04.000000000 -0500
-@@ -0,0 +1,396 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/config.h"
-+#include "linux/kernel.h"
-+#include "linux/sched.h"
-+#include "linux/interrupt.h"
-+#include "linux/mm.h"
-+#include "linux/slab.h"
-+#include "linux/utsname.h"
-+#include "linux/fs.h"
-+#include "linux/utime.h"
-+#include "linux/smp_lock.h"
-+#include "linux/module.h"
-+#include "linux/init.h"
-+#include "linux/capability.h"
-+#include "asm/unistd.h"
-+#include "asm/mman.h"
-+#include "asm/segment.h"
-+#include "asm/stat.h"
-+#include "asm/pgtable.h"
-+#include "asm/processor.h"
-+#include "asm/pgalloc.h"
-+#include "asm/spinlock.h"
-+#include "asm/uaccess.h"
-+#include "asm/user.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "kern.h"
-+#include "signal_kern.h"
-+#include "signal_user.h"
-+#include "init.h"
-+#include "irq_user.h"
-+#include "mem_user.h"
-+#include "time_user.h"
-+#include "tlb.h"
-+#include "frame_kern.h"
-+#include "sigcontext.h"
-+#include "2_5compat.h"
-+#include "os.h"
-+#include "mode.h"
-+#include "mode_kern.h"
-+#include "choose-mode.h"
-+
-+/* This is a per-cpu array. A processor only modifies its entry and it only
-+ * cares about its entry, so it's OK if another processor is modifying its
-+ * entry.
-+ */
-+struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
-+
-+struct task_struct *get_task(int pid, int require)
-+{
-+ struct task_struct *ret;
-+
-+ read_lock(&tasklist_lock);
-+ ret = find_task_by_pid(pid);
-+ read_unlock(&tasklist_lock);
-+
-+ if(require && (ret == NULL)) panic("get_task couldn't find a task\n");
-+ return(ret);
-+}
-+
-+int external_pid(void *t)
-+{
-+ struct task_struct *task = t ? t : current;
-+
-+ return(CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task));
-+}
-+
-+int pid_to_processor_id(int pid)
-+{
-+ int i;
-+
-+ for(i = 0; i < smp_num_cpus; i++){
-+ if(cpu_tasks[i].pid == pid) return(i);
-+ }
-+ return(-1);
-+}
-+
-+void free_stack(unsigned long stack, int order)
-+{
-+ free_pages(stack, order);
-+}
-+
-+unsigned long alloc_stack(int order, int atomic)
-+{
-+ unsigned long page;
-+ int flags = GFP_KERNEL;
-+
-+ if(atomic) flags |= GFP_ATOMIC;
-+ page = __get_free_pages(flags, order);
-+ if(page == 0)
-+ return(0);
-+ stack_protections(page);
-+ return(page);
-+}
-+
-+int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-+{
-+ int pid;
-+
-+ current->thread.request.u.thread.proc = fn;
-+ current->thread.request.u.thread.arg = arg;
-+ pid = do_fork(CLONE_VM | flags, 0, NULL, 0);
-+#if 0 /* CLONE_UNTRACED for 2.6 */
-+ pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, NULL, 0);
-+#endif
-+ if(pid < 0)
-+ panic("do_fork failed in kernel_thread, errno = %d", pid);
-+ return(pid);
-+}
-+
-+void switch_mm(struct mm_struct *prev, struct mm_struct *next,
-+ struct task_struct *tsk, unsigned cpu)
-+{
-+ if (prev != next)
-+ clear_bit(cpu, &prev->cpu_vm_mask);
-+ set_bit(cpu, &next->cpu_vm_mask);
-+}
-+
-+void set_current(void *t)
-+{
-+ struct task_struct *task = t;
-+
-+ cpu_tasks[task->processor] = ((struct cpu_task)
-+ { external_pid(task), task });
-+}
-+
-+void *_switch_to(void *prev, void *next)
-+{
-+ return(CHOOSE_MODE(_switch_to_tt(prev, next),
-+ _switch_to_skas(prev, next)));
-+}
-+
-+void interrupt_end(void)
-+{
-+ if(current->need_resched) schedule();
-+ if(current->sigpending != 0) do_signal(0);
-+}
-+
-+void release_thread(struct task_struct *task)
-+{
-+ CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task));
-+}
-+
-+void exit_thread(void)
-+{
-+ CHOOSE_MODE(exit_thread_tt(), exit_thread_skas());
-+ unprotect_stack((unsigned long) current);
-+}
-+
-+void *get_current(void)
-+{
-+ return(current);
-+}
-+
-+int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
-+ unsigned long stack_top, struct task_struct * p,
-+ struct pt_regs *regs)
-+{
-+ p->thread = (struct thread_struct) INIT_THREAD;
-+ p->thread.kernel_stack = (unsigned long) p + 2 * PAGE_SIZE;
-+
-+ return(CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr,
-+ clone_flags, sp, stack_top, p, regs));
-+}
-+
-+void initial_thread_cb(void (*proc)(void *), void *arg)
-+{
-+ int save_kmalloc_ok = kmalloc_ok;
-+
-+ kmalloc_ok = 0;
-+ CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc,
-+ arg);
-+ kmalloc_ok = save_kmalloc_ok;
-+}
-+
-+unsigned long stack_sp(unsigned long page)
-+{
-+ return(page + PAGE_SIZE - sizeof(void *));
-+}
-+
-+int current_pid(void)
-+{
-+ return(current->pid);
-+}
-+
-+void cpu_idle(void)
-+{
-+ CHOOSE_MODE(init_idle_tt(), init_idle_skas());
-+
-+ atomic_inc(&init_mm.mm_count);
-+ current->mm = &init_mm;
-+ current->active_mm = &init_mm;
-+
-+ while(1){
-+ /* endless idle loop with no priority at all */
-+ SET_PRI(current);
-+
-+ /*
-+ * although we are an idle CPU, we do not want to
-+ * get into the scheduler unnecessarily.
-+ */
-+ if (current->need_resched) {
-+ schedule();
-+ check_pgt_cache();
-+ }
-+ idle_sleep(10);
-+ }
-+}
-+
-+int page_size(void)
-+{
-+ return(PAGE_SIZE);
-+}
-+
-+int page_mask(void)
-+{
-+ return(PAGE_MASK);
-+}
-+
-+void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
-+ pte_t *pte_out)
-+{
-+ pgd_t *pgd;
-+ pmd_t *pmd;
-+ pte_t *pte;
-+
-+ if(task->mm == NULL)
-+ return(ERR_PTR(-EINVAL));
-+ pgd = pgd_offset(task->mm, addr);
-+ pmd = pmd_offset(pgd, addr);
-+ if(!pmd_present(*pmd))
-+ return(ERR_PTR(-EINVAL));
-+ pte = pte_offset(pmd, addr);
-+ if(!pte_present(*pte))
-+ return(ERR_PTR(-EINVAL));
-+ if(pte_out != NULL)
-+ *pte_out = *pte;
-+ return((void *) (pte_val(*pte) & PAGE_MASK) + (addr & ~PAGE_MASK));
-+}
-+
-+char *current_cmd(void)
-+{
-+#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM)
-+ return("(Unknown)");
-+#else
-+ void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL);
-+ return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr);
-+#endif
-+}
-+
-+void force_sigbus(void)
-+{
-+ printk(KERN_ERR "Killing pid %d because of a lack of memory\n",
-+ current->pid);
-+ lock_kernel();
-+ sigaddset(¤t->pending.signal, SIGBUS);
-+ recalc_sigpending(current);
-+ current->flags |= PF_SIGNALED;
-+ do_exit(SIGBUS | 0x80);
-+}
-+
-+void dump_thread(struct pt_regs *regs, struct user *u)
-+{
-+}
-+
-+void enable_hlt(void)
-+{
-+ panic("enable_hlt");
-+}
-+
-+void disable_hlt(void)
-+{
-+ panic("disable_hlt");
-+}
-+
-+extern int signal_frame_size;
-+
-+void *um_kmalloc(int size)
-+{
-+ return(kmalloc(size, GFP_KERNEL));
-+}
-+
-+void *um_kmalloc_atomic(int size)
-+{
-+ return(kmalloc(size, GFP_ATOMIC));
-+}
-+
-+unsigned long get_fault_addr(void)
-+{
-+ return((unsigned long) current->thread.fault_addr);
-+}
-+
-+EXPORT_SYMBOL(get_fault_addr);
-+
-+void not_implemented(void)
-+{
-+ printk(KERN_DEBUG "Something isn't implemented in here\n");
-+}
-+
-+EXPORT_SYMBOL(not_implemented);
-+
-+int user_context(unsigned long sp)
-+{
-+ unsigned long stack;
-+
-+ stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER);
-+ stack += 2 * PAGE_SIZE;
-+ return(stack != current->thread.kernel_stack);
-+}
-+
-+extern void remove_umid_dir(void);
-+
-+__uml_exitcall(remove_umid_dir);
-+
-+extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
-+
-+void do_uml_exitcalls(void)
-+{
-+ exitcall_t *call;
-+
-+ call = &__uml_exitcall_end;
-+ while (--call >= &__uml_exitcall_begin)
-+ (*call)();
-+}
-+
-+char *uml_strdup(char *string)
-+{
-+ char *new;
-+
-+ new = kmalloc(strlen(string) + 1, GFP_KERNEL);
-+ if(new == NULL) return(NULL);
-+ strcpy(new, string);
-+ return(new);
-+}
-+
-+void *get_init_task(void)
-+{
-+ return(&init_task_union.task);
-+}
-+
-+int copy_to_user_proc(void *to, void *from, int size)
-+{
-+ return(copy_to_user(to, from, size));
-+}
-+
-+int copy_from_user_proc(void *to, void *from, int size)
-+{
-+ return(copy_from_user(to, from, size));
-+}
-+
-+int clear_user_proc(void *buf, int size)
-+{
-+ return(clear_user(buf, size));
-+}
-+
-+int strlen_user_proc(char *str)
-+{
-+ return(strlen_user(str));
-+}
-+
-+int smp_sigio_handler(void)
-+{
-+#ifdef CONFIG_SMP
-+ int cpu = current->processor;
-+
-+ IPI_handler(cpu);
-+ if(cpu != 0)
-+ return(1);
-+#endif
-+ return(0);
-+}
-+
-+int um_in_interrupt(void)
-+{
-+ return(in_interrupt());
-+}
-+
-+int cpu(void)
-+{
-+ return(current->processor);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/ptrace.c um/arch/um/kernel/ptrace.c
---- orig/arch/um/kernel/ptrace.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/ptrace.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,325 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/sched.h"
-+#include "linux/mm.h"
-+#include "linux/errno.h"
-+#include "linux/smp_lock.h"
-+#ifdef CONFIG_PROC_MM
-+#include "linux/proc_mm.h"
-+#endif
-+#include "asm/ptrace.h"
-+#include "asm/uaccess.h"
-+#include "kern_util.h"
-+#include "ptrace_user.h"
-+
-+/*
-+ * Called by kernel/ptrace.c when detaching..
-+ */
-+void ptrace_disable(struct task_struct *child)
-+{
-+}
-+
-+extern long do_mmap2(struct task_struct *task, unsigned long addr,
-+ unsigned long len, unsigned long prot,
-+ unsigned long flags, unsigned long fd,
-+ unsigned long pgoff);
-+
-+int sys_ptrace(long request, long pid, long addr, long data)
-+{
-+ struct task_struct *child;
-+ int i, ret;
-+
-+ lock_kernel();
-+ ret = -EPERM;
-+ if (request == PTRACE_TRACEME) {
-+ /* are we already being traced? */
-+ if (current->ptrace & PT_PTRACED)
-+ goto out;
-+ /* set the ptrace bit in the process flags. */
-+ current->ptrace |= PT_PTRACED;
-+ ret = 0;
-+ goto out;
-+ }
-+ ret = -ESRCH;
-+ read_lock(&tasklist_lock);
-+ child = find_task_by_pid(pid);
-+ if (child)
-+ get_task_struct(child);
-+ read_unlock(&tasklist_lock);
-+ if (!child)
-+ goto out;
-+
-+ ret = -EPERM;
-+ if (pid == 1) /* you may not mess with init */
-+ goto out_tsk;
-+
-+ if (request == PTRACE_ATTACH) {
-+ ret = ptrace_attach(child);
-+ goto out_tsk;
-+ }
-+
-+ ret = ptrace_check_attach(child, request == PTRACE_KILL);
-+ if (ret < 0)
-+ goto out_tsk;
-+
-+ switch (request) {
-+ /* when I and D space are separate, these will need to be fixed. */
-+ case PTRACE_PEEKTEXT: /* read word at location addr. */
-+ case PTRACE_PEEKDATA: {
-+ unsigned long tmp;
-+ int copied;
-+
-+ ret = -EIO;
-+ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-+ if (copied != sizeof(tmp))
-+ break;
-+ ret = put_user(tmp,(unsigned long *) data);
-+ break;
-+ }
-+
-+ /* read the word at location addr in the USER area. */
-+ case PTRACE_PEEKUSR: {
-+ unsigned long tmp;
-+
-+ ret = -EIO;
-+ if ((addr & 3) || addr < 0)
-+ break;
-+
-+ tmp = 0; /* Default return condition */
-+ if(addr < FRAME_SIZE_OFFSET){
-+ tmp = getreg(child, addr);
-+ }
-+ else if((addr >= offsetof(struct user, u_debugreg[0])) &&
-+ (addr <= offsetof(struct user, u_debugreg[7]))){
-+ addr -= offsetof(struct user, u_debugreg[0]);
-+ addr = addr >> 2;
-+ tmp = child->thread.arch.debugregs[addr];
-+ }
-+ ret = put_user(tmp, (unsigned long *) data);
-+ break;
-+ }
-+
-+ /* when I and D space are separate, this will have to be fixed. */
-+ case PTRACE_POKETEXT: /* write the word at location addr. */
-+ case PTRACE_POKEDATA:
-+ ret = -EIO;
-+ if (access_process_vm(child, addr, &data, sizeof(data),
-+ 1) != sizeof(data))
-+ break;
-+ ret = 0;
-+ break;
-+
-+ case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
-+ ret = -EIO;
-+ if ((addr & 3) || addr < 0)
-+ break;
-+
-+ if (addr < FRAME_SIZE_OFFSET) {
-+ ret = putreg(child, addr, data);
-+ break;
-+ }
-+ else if((addr >= offsetof(struct user, u_debugreg[0])) &&
-+ (addr <= offsetof(struct user, u_debugreg[7]))){
-+ addr -= offsetof(struct user, u_debugreg[0]);
-+ addr = addr >> 2;
-+ if((addr == 4) || (addr == 5)) break;
-+ child->thread.arch.debugregs[addr] = data;
-+ ret = 0;
-+ }
-+
-+ break;
-+
-+ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
-+ case PTRACE_CONT: { /* restart after signal. */
-+ ret = -EIO;
-+ if ((unsigned long) data > _NSIG)
-+ break;
-+ if (request == PTRACE_SYSCALL)
-+ child->ptrace |= PT_TRACESYS;
-+ else
-+ child->ptrace &= ~PT_TRACESYS;
-+ child->exit_code = data;
-+ wake_up_process(child);
-+ ret = 0;
-+ break;
-+ }
-+
-+/*
-+ * make the child exit. Best I can do is send it a sigkill.
-+ * perhaps it should be put in the status that it wants to
-+ * exit.
-+ */
-+ case PTRACE_KILL: {
-+ ret = 0;
-+ if (child->state == TASK_ZOMBIE) /* already dead */
-+ break;
-+ child->exit_code = SIGKILL;
-+ wake_up_process(child);
-+ break;
-+ }
-+
-+ case PTRACE_SINGLESTEP: { /* set the trap flag. */
-+ ret = -EIO;
-+ if ((unsigned long) data > _NSIG)
-+ break;
-+ child->ptrace &= ~PT_TRACESYS;
-+ child->ptrace |= PT_DTRACE;
-+ child->exit_code = data;
-+ /* give it a chance to run. */
-+ wake_up_process(child);
-+ ret = 0;
-+ break;
-+ }
-+
-+ case PTRACE_DETACH:
-+ /* detach a process that was attached. */
-+ ret = ptrace_detach(child, data);
-+ break;
-+
-+#ifdef PTRACE_GETREGS
-+ case PTRACE_GETREGS: { /* Get all gp regs from the child. */
-+ if (!access_ok(VERIFY_WRITE, (unsigned long *)data,
-+ FRAME_SIZE_OFFSET)) {
-+ ret = -EIO;
-+ break;
-+ }
-+ for ( i = 0; i < FRAME_SIZE_OFFSET; i += sizeof(long) ) {
-+ __put_user(getreg(child, i), (unsigned long *) data);
-+ data += sizeof(long);
-+ }
-+ ret = 0;
-+ break;
-+ }
-+#endif
-+#ifdef PTRACE_SETREGS
-+ case PTRACE_SETREGS: { /* Set all gp regs in the child. */
-+ unsigned long tmp = 0;
-+ if (!access_ok(VERIFY_READ, (unsigned *)data,
-+ FRAME_SIZE_OFFSET)) {
-+ ret = -EIO;
-+ break;
-+ }
-+ for ( i = 0; i < FRAME_SIZE_OFFSET; i += sizeof(long) ) {
-+ __get_user(tmp, (unsigned long *) data);
-+ putreg(child, i, tmp);
-+ data += sizeof(long);
-+ }
-+ ret = 0;
-+ break;
-+ }
-+#endif
-+#ifdef PTRACE_GETFPREGS
-+ case PTRACE_GETFPREGS: /* Get the child FPU state. */
-+ ret = get_fpregs(data, child);
-+ break;
-+#endif
-+#ifdef PTRACE_SETFPREGS
-+ case PTRACE_SETFPREGS: /* Set the child FPU state. */
-+ ret = set_fpregs(data, child);
-+ break;
-+#endif
-+#ifdef PTRACE_GETFPXREGS
-+ case PTRACE_GETFPXREGS: /* Get the child FPU state. */
-+ ret = get_fpxregs(data, child);
-+ break;
-+#endif
-+#ifdef PTRACE_SETFPXREGS
-+ case PTRACE_SETFPXREGS: /* Set the child FPU state. */
-+ ret = set_fpxregs(data, child);
-+ break;
-+#endif
-+ case PTRACE_FAULTINFO: {
-+ struct ptrace_faultinfo fault;
-+
-+ fault = ((struct ptrace_faultinfo)
-+ { .is_write = child->thread.err,
-+ .addr = child->thread.cr2 });
-+ ret = copy_to_user((unsigned long *) data, &fault,
-+ sizeof(fault));
-+ if(ret)
-+ break;
-+ break;
-+ }
-+ case PTRACE_SIGPENDING:
-+ ret = copy_to_user((unsigned long *) data,
-+ &child->pending.signal,
-+ sizeof(child->pending.signal));
-+ break;
-+
-+ case PTRACE_LDT: {
-+ struct ptrace_ldt ldt;
-+
-+ if(copy_from_user(&ldt, (unsigned long *) data,
-+ sizeof(ldt))){
-+ ret = -EIO;
-+ break;
-+ }
-+
-+ /* This one is confusing, so just punt and return -EIO for
-+ * now
-+ */
-+ ret = -EIO;
-+ break;
-+ }
-+#ifdef CONFIG_PROC_MM
-+ case PTRACE_SWITCH_MM: {
-+ struct mm_struct *old = child->mm;
-+ struct mm_struct *new = proc_mm_get_mm(data);
-+
-+ if(IS_ERR(new)){
-+ ret = PTR_ERR(new);
-+ break;
-+ }
-+
-+ atomic_inc(&new->mm_users);
-+ child->mm = new;
-+ child->active_mm = new;
-+ mmput(old);
-+ ret = 0;
-+ break;
-+ }
-+#endif
-+ default:
-+ ret = -EIO;
-+ break;
-+ }
-+ out_tsk:
-+ free_task_struct(child);
-+ out:
-+ unlock_kernel();
-+ return ret;
-+}
-+
-+void syscall_trace(void)
-+{
-+ if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
-+ != (PT_PTRACED|PT_TRACESYS))
-+ return;
-+ current->exit_code = SIGTRAP;
-+ current->state = TASK_STOPPED;
-+ notify_parent(current, SIGCHLD);
-+ schedule();
-+ /*
-+ * this isn't the same as continuing with a signal, but it will do
-+ * for normal use. strace only continues with a signal if the
-+ * stopping signal is not SIGTRAP. -brl
-+ */
-+ if (current->exit_code) {
-+ send_sig(current->exit_code, current, 1);
-+ current->exit_code = 0;
-+ }
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/reboot.c um/arch/um/kernel/reboot.c
---- orig/arch/um/kernel/reboot.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/reboot.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,73 @@
-+/*
-+ * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/sched.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "kern.h"
-+#include "os.h"
-+#include "mode.h"
-+#include "choose-mode.h"
-+
-+#ifdef CONFIG_SMP
-+static void kill_idlers(int me)
-+{
-+#ifdef CONFIG_MODE_TT
-+ struct task_struct *p;
-+ int i;
-+
-+ for(i = 0; i < sizeof(init_tasks)/sizeof(init_tasks[0]); i++){
-+ p = init_tasks[i];
-+ if((p != NULL) && (p->thread.mode.tt.extern_pid != me) &&
-+ (p->thread.mode.tt.extern_pid != -1))
-+ os_kill_process(p->thread.mode.tt.extern_pid, 0);
-+ }
-+#endif
-+}
-+#endif
-+
-+static void kill_off_processes(void)
-+{
-+ CHOOSE_MODE(kill_off_processes_tt(), kill_off_processes_skas());
-+#ifdef CONFIG_SMP
-+ kill_idlers(os_getpid());
-+#endif
-+}
-+
-+void uml_cleanup(void)
-+{
-+ kill_off_processes();
-+ do_uml_exitcalls();
-+}
-+
-+void machine_restart(char * __unused)
-+{
-+ do_uml_exitcalls();
-+ kill_off_processes();
-+ CHOOSE_MODE(reboot_tt(), reboot_skas());
-+}
-+
-+void machine_power_off(void)
-+{
-+ do_uml_exitcalls();
-+ kill_off_processes();
-+ CHOOSE_MODE(halt_tt(), halt_skas());
-+}
-+
-+void machine_halt(void)
-+{
-+ machine_power_off();
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/resource.c um/arch/um/kernel/resource.c
---- orig/arch/um/kernel/resource.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/resource.c 2003-10-21 03:26:06.000000000 -0400
-@@ -0,0 +1,23 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/pci.h"
-+
-+unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
-+ unsigned long start, unsigned long size)
-+{
-+ return start;
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/sigio_kern.c um/arch/um/kernel/sigio_kern.c
---- orig/arch/um/kernel/sigio_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/sigio_kern.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,57 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/kernel.h"
-+#include "linux/list.h"
-+#include "linux/slab.h"
-+#include "asm/irq.h"
-+#include "init.h"
-+#include "sigio.h"
-+#include "irq_user.h"
-+#include "irq_kern.h"
-+
-+/* Protected by sigio_lock() called from write_sigio_workaround */
-+static int sigio_irq_fd = -1;
-+
-+void sigio_interrupt(int irq, void *data, struct pt_regs *unused)
-+{
-+ read_sigio_fd(sigio_irq_fd);
-+ reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ);
-+}
-+
-+int write_sigio_irq(int fd)
-+{
-+ if(um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt,
-+ SA_INTERRUPT | SA_SAMPLE_RANDOM, "write sigio",
-+ NULL)){
-+ printk("write_sigio_irq : um_request_irq failed\n");
-+ return(-1);
-+ }
-+ sigio_irq_fd = fd;
-+ return(0);
-+}
-+
-+static spinlock_t sigio_spinlock = SPIN_LOCK_UNLOCKED;
-+
-+void sigio_lock(void)
-+{
-+ spin_lock(&sigio_spinlock);
-+}
-+
-+void sigio_unlock(void)
-+{
-+ spin_unlock(&sigio_spinlock);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/sigio_user.c um/arch/um/kernel/sigio_user.c
---- orig/arch/um/kernel/sigio_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/sigio_user.c 2003-11-07 01:41:13.000000000 -0500
-@@ -0,0 +1,438 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <unistd.h>
-+#include <stdlib.h>
-+#include <termios.h>
-+#include <pty.h>
-+#include <signal.h>
-+#include <errno.h>
-+#include <string.h>
-+#include <sched.h>
-+#include <sys/socket.h>
-+#include <sys/poll.h>
-+#include "init.h"
-+#include "user.h"
-+#include "kern_util.h"
-+#include "sigio.h"
-+#include "helper.h"
-+#include "os.h"
-+
-+/* Changed during early boot */
-+int pty_output_sigio = 0;
-+int pty_close_sigio = 0;
-+
-+/* Used as a flag during SIGIO testing early in boot */
-+static volatile int got_sigio = 0;
-+
-+void __init handler(int sig)
-+{
-+ got_sigio = 1;
-+}
-+
-+struct openpty_arg {
-+ int master;
-+ int slave;
-+ int err;
-+};
-+
-+static void openpty_cb(void *arg)
-+{
-+ struct openpty_arg *info = arg;
-+
-+ info->err = 0;
-+ if(openpty(&info->master, &info->slave, NULL, NULL, NULL))
-+ info->err = -errno;
-+}
-+
-+void __init check_one_sigio(void (*proc)(int, int))
-+{
-+ struct sigaction old, new;
-+ struct termios tt;
-+ struct openpty_arg pty = { .master = -1, .slave = -1 };
-+ int master, slave, err;
-+
-+ initial_thread_cb(openpty_cb, &pty);
-+ if(pty.err){
-+ printk("openpty failed, errno = %d\n", -pty.err);
-+ return;
-+ }
-+
-+ master = pty.master;
-+ slave = pty.slave;
-+
-+ if((master == -1) || (slave == -1)){
-+ printk("openpty failed to allocate a pty\n");
-+ return;
-+ }
-+
-+ /* XXX These can fail with EINTR */
-+ if(tcgetattr(master, &tt) < 0)
-+ panic("check_sigio : tcgetattr failed, errno = %d\n", errno);
-+ cfmakeraw(&tt);
-+ if(tcsetattr(master, TCSADRAIN, &tt) < 0)
-+ panic("check_sigio : tcsetattr failed, errno = %d\n", errno);
-+
-+ err = os_sigio_async(master, slave);
-+ if(err < 0)
-+ panic("tty_fds : sigio_async failed, err = %d\n", -err);
-+
-+ if(sigaction(SIGIO, NULL, &old) < 0)
-+ panic("check_sigio : sigaction 1 failed, errno = %d\n", errno);
-+ new = old;
-+ new.sa_handler = handler;
-+ if(sigaction(SIGIO, &new, NULL) < 0)
-+ panic("check_sigio : sigaction 2 failed, errno = %d\n", errno);
-+
-+ got_sigio = 0;
-+ (*proc)(master, slave);
-+
-+ os_close_file(master);
-+ os_close_file(slave);
-+
-+ if(sigaction(SIGIO, &old, NULL) < 0)
-+ panic("check_sigio : sigaction 3 failed, errno = %d\n", errno);
-+}
-+
-+static void tty_output(int master, int slave)
-+{
-+ int n;
-+ char buf[512];
-+
-+ printk("Checking that host ptys support output SIGIO...");
-+
-+ memset(buf, 0, sizeof(buf));
-+
-+ while(os_write_file(master, buf, sizeof(buf)) > 0) ;
-+ if(errno != EAGAIN)
-+ panic("check_sigio : write failed, errno = %d\n", errno);
-+ while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
-+
-+ if(got_sigio){
-+ printk("Yes\n");
-+ pty_output_sigio = 1;
-+ }
-+ else if(n == -EAGAIN) printk("No, enabling workaround\n");
-+ else panic("check_sigio : read failed, err = %d\n", n);
-+}
-+
-+static void tty_close(int master, int slave)
-+{
-+ printk("Checking that host ptys support SIGIO on close...");
-+
-+ os_close_file(slave);
-+ if(got_sigio){
-+ printk("Yes\n");
-+ pty_close_sigio = 1;
-+ }
-+ else printk("No, enabling workaround\n");
-+}
-+
-+void __init check_sigio(void)
-+{
-+ if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) &&
-+ (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){
-+ printk("No pseudo-terminals available - skipping pty SIGIO "
-+ "check\n");
-+ return;
-+ }
-+ check_one_sigio(tty_output);
-+ check_one_sigio(tty_close);
-+}
-+
-+/* Protected by sigio_lock(), also used by sigio_cleanup, which is an
-+ * exitcall.
-+ */
-+static int write_sigio_pid = -1;
-+
-+/* These arrays are initialized before the sigio thread is started, and
-+ * the descriptors closed after it is killed. So, it can't see them change.
-+ * On the UML side, they are changed under the sigio_lock.
-+ */
-+static int write_sigio_fds[2] = { -1, -1 };
-+static int sigio_private[2] = { -1, -1 };
-+
-+struct pollfds {
-+ struct pollfd *poll;
-+ int size;
-+ int used;
-+};
-+
-+/* Protected by sigio_lock(). Used by the sigio thread, but the UML thread
-+ * synchronizes with it.
-+ */
-+struct pollfds current_poll = {
-+ .poll = NULL,
-+ .size = 0,
-+ .used = 0
-+};
-+
-+struct pollfds next_poll = {
-+ .poll = NULL,
-+ .size = 0,
-+ .used = 0
-+};
-+
-+static int write_sigio_thread(void *unused)
-+{
-+ struct pollfds *fds, tmp;
-+ struct pollfd *p;
-+ int i, n, respond_fd;
-+ char c;
-+
-+ fds = ¤t_poll;
-+ while(1){
-+ n = poll(fds->poll, fds->used, -1);
-+ if(n < 0){
-+ if(errno == EINTR) continue;
-+ printk("write_sigio_thread : poll returned %d, "
-+ "errno = %d\n", n, errno);
-+ }
-+ for(i = 0; i < fds->used; i++){
-+ p = &fds->poll[i];
-+ if(p->revents == 0) continue;
-+ if(p->fd == sigio_private[1]){
-+ n = os_read_file(sigio_private[1], &c, sizeof(c));
-+ if(n != sizeof(c))
-+ printk("write_sigio_thread : "
-+ "read failed, err = %d\n", -n);
-+ tmp = current_poll;
-+ current_poll = next_poll;
-+ next_poll = tmp;
-+ respond_fd = sigio_private[1];
-+ }
-+ else {
-+ respond_fd = write_sigio_fds[1];
-+ fds->used--;
-+ memmove(&fds->poll[i], &fds->poll[i + 1],
-+ (fds->used - i) * sizeof(*fds->poll));
-+ }
-+
-+ n = os_write_file(respond_fd, &c, sizeof(c));
-+ if(n != sizeof(c))
-+ printk("write_sigio_thread : write failed, "
-+ "err = %d\n", -n);
-+ }
-+ }
-+}
-+
-+static int need_poll(int n)
-+{
-+ if(n <= next_poll.size){
-+ next_poll.used = n;
-+ return(0);
-+ }
-+ if(next_poll.poll != NULL) kfree(next_poll.poll);
-+ next_poll.poll = um_kmalloc_atomic(n * sizeof(struct pollfd));
-+ if(next_poll.poll == NULL){
-+ printk("need_poll : failed to allocate new pollfds\n");
-+ next_poll.size = 0;
-+ next_poll.used = 0;
-+ return(-1);
-+ }
-+ next_poll.size = n;
-+ next_poll.used = n;
-+ return(0);
-+}
-+
-+static void update_thread(void)
-+{
-+ unsigned long flags;
-+ int n;
-+ char c;
-+
-+ flags = set_signals(0);
-+ n = os_write_file(sigio_private[0], &c, sizeof(c));
-+ if(n != sizeof(c)){
-+ printk("update_thread : write failed, err = %d\n", -n);
-+ goto fail;
-+ }
-+
-+ n = os_read_file(sigio_private[0], &c, sizeof(c));
-+ if(n != sizeof(c)){
-+ printk("update_thread : read failed, err = %d\n", -n);
-+ goto fail;
-+ }
-+
-+ set_signals(flags);
-+ return;
-+ fail:
-+ sigio_lock();
-+ if(write_sigio_pid != -1)
-+ os_kill_process(write_sigio_pid, 1);
-+ write_sigio_pid = -1;
-+ os_close_file(sigio_private[0]);
-+ os_close_file(sigio_private[1]);
-+ os_close_file(write_sigio_fds[0]);
-+ os_close_file(write_sigio_fds[1]);
-+ sigio_unlock();
-+ set_signals(flags);
-+}
-+
-+int add_sigio_fd(int fd, int read)
-+{
-+ int err = 0, i, n, events;
-+
-+ sigio_lock();
-+ for(i = 0; i < current_poll.used; i++){
-+ if(current_poll.poll[i].fd == fd)
-+ goto out;
-+ }
-+
-+ n = current_poll.used + 1;
-+ err = need_poll(n);
-+ if(err)
-+ goto out;
-+
-+ for(i = 0; i < current_poll.used; i++)
-+ next_poll.poll[i] = current_poll.poll[i];
-+
-+ if(read) events = POLLIN;
-+ else events = POLLOUT;
-+
-+ next_poll.poll[n - 1] = ((struct pollfd) { .fd = fd,
-+ .events = events,
-+ .revents = 0 });
-+ update_thread();
-+ out:
-+ sigio_unlock();
-+ return(err);
-+}
-+
-+int ignore_sigio_fd(int fd)
-+{
-+ struct pollfd *p;
-+ int err = 0, i, n = 0;
-+
-+ sigio_lock();
-+ for(i = 0; i < current_poll.used; i++){
-+ if(current_poll.poll[i].fd == fd) break;
-+ }
-+ if(i == current_poll.used)
-+ goto out;
-+
-+ err = need_poll(current_poll.used - 1);
-+ if(err)
-+ goto out;
-+
-+ for(i = 0; i < current_poll.used; i++){
-+ p = ¤t_poll.poll[i];
-+ if(p->fd != fd) next_poll.poll[n++] = current_poll.poll[i];
-+ }
-+ if(n == i){
-+ printk("ignore_sigio_fd : fd %d not found\n", fd);
-+ err = -1;
-+ goto out;
-+ }
-+
-+ update_thread();
-+ out:
-+ sigio_unlock();
-+ return(err);
-+}
-+
-+static int setup_initial_poll(int fd)
-+{
-+ struct pollfd *p;
-+
-+ p = um_kmalloc(sizeof(struct pollfd));
-+ if(p == NULL){
-+ printk("setup_initial_poll : failed to allocate poll\n");
-+ return(-1);
-+ }
-+ *p = ((struct pollfd) { .fd = fd,
-+ .events = POLLIN,
-+ .revents = 0 });
-+ current_poll = ((struct pollfds) { .poll = p,
-+ .used = 1,
-+ .size = 1 });
-+ return(0);
-+}
-+
-+void write_sigio_workaround(void)
-+{
-+ unsigned long stack;
-+ int err;
-+
-+ sigio_lock();
-+ if(write_sigio_pid != -1)
-+ goto out;
-+
-+ err = os_pipe(write_sigio_fds, 1, 1);
-+ if(err < 0){
-+ printk("write_sigio_workaround - os_pipe 1 failed, "
-+ "err = %d\n", -err);
-+ goto out;
-+ }
-+ err = os_pipe(sigio_private, 1, 1);
-+ if(err < 0){
-+ printk("write_sigio_workaround - os_pipe 2 failed, "
-+ "err = %d\n", -err);
-+ goto out_close1;
-+ }
-+ if(setup_initial_poll(sigio_private[1]))
-+ goto out_close2;
-+
-+ write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
-+ CLONE_FILES | CLONE_VM, &stack, 0);
-+
-+ if(write_sigio_pid < 0) goto out_close2;
-+
-+ if(write_sigio_irq(write_sigio_fds[0]))
-+ goto out_kill;
-+
-+ out:
-+ sigio_unlock();
-+ return;
-+
-+ out_kill:
-+ os_kill_process(write_sigio_pid, 1);
-+ write_sigio_pid = -1;
-+ out_close2:
-+ os_close_file(sigio_private[0]);
-+ os_close_file(sigio_private[1]);
-+ out_close1:
-+ os_close_file(write_sigio_fds[0]);
-+ os_close_file(write_sigio_fds[1]);
-+ sigio_unlock();
-+}
-+
-+int read_sigio_fd(int fd)
-+{
-+ int n;
-+ char c;
-+
-+ n = os_read_file(fd, &c, sizeof(c));
-+ if(n != sizeof(c)){
-+ if(n < 0) {
-+ printk("read_sigio_fd - read failed, err = %d\n", -n);
-+ return(n);
-+ }
-+ else {
-+ printk("read_sigio_fd - short read, bytes = %d\n", n);
-+ return(-EIO);
-+ }
-+ }
-+ return(n);
-+}
-+
-+static void sigio_cleanup(void)
-+{
-+ if(write_sigio_pid != -1)
-+ os_kill_process(write_sigio_pid, 1);
-+}
-+
-+__uml_exitcall(sigio_cleanup);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/signal_kern.c um/arch/um/kernel/signal_kern.c
---- orig/arch/um/kernel/signal_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/signal_kern.c 2003-11-19 03:50:58.000000000 -0500
-@@ -0,0 +1,369 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/config.h"
-+#include "linux/stddef.h"
-+#include "linux/sys.h"
-+#include "linux/sched.h"
-+#include "linux/wait.h"
-+#include "linux/kernel.h"
-+#include "linux/smp_lock.h"
-+#include "linux/module.h"
-+#include "linux/slab.h"
-+#include "asm/signal.h"
-+#include "asm/uaccess.h"
-+#include "asm/ucontext.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "signal_kern.h"
-+#include "signal_user.h"
-+#include "kern.h"
-+#include "frame_kern.h"
-+#include "sigcontext.h"
-+#include "mode.h"
-+
-+EXPORT_SYMBOL(block_signals);
-+EXPORT_SYMBOL(unblock_signals);
-+
-+static void force_segv(int sig)
-+{
-+ if(sig == SIGSEGV){
-+ struct k_sigaction *ka;
-+
-+ ka = ¤t->sig->action[SIGSEGV - 1];
-+ ka->sa.sa_handler = SIG_DFL;
-+ }
-+ force_sig(SIGSEGV, current);
-+}
-+
-+#define _S(nr) (1<<((nr)-1))
-+
-+#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
-+
-+/*
-+ * OK, we're invoking a handler
-+ */
-+static int handle_signal(struct pt_regs *regs, unsigned long signr,
-+ struct k_sigaction *ka, siginfo_t *info,
-+ sigset_t *oldset, int error)
-+{
-+ __sighandler_t handler;
-+ void (*restorer)(void);
-+ unsigned long sp;
-+ sigset_t save;
-+ int err, ret;
-+
-+ ret = 0;
-+ switch(error){
-+ case -ERESTARTNOHAND:
-+ ret = -EINTR;
-+ break;
-+
-+ case -ERESTARTSYS:
-+ if (!(ka->sa.sa_flags & SA_RESTART)) {
-+ ret = -EINTR;
-+ break;
-+ }
-+ /* fallthrough */
-+ case -ERESTARTNOINTR:
-+ PT_REGS_RESTART_SYSCALL(regs);
-+ PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
-+
-+ /* This is because of the UM_SET_SYSCALL_RETURN and the fact
-+ * that on i386 the system call number and return value are
-+ * in the same register. When the system call restarts, %eax
-+ * had better have the system call number in it. Since the
-+ * return value doesn't matter (except that it shouldn't be
-+ * -ERESTART*), we'll stick the system call number there.
-+ */
-+ ret = PT_REGS_SYSCALL_NR(regs);
-+ break;
-+ }
-+
-+ handler = ka->sa.sa_handler;
-+ save = *oldset;
-+
-+ if (ka->sa.sa_flags & SA_ONESHOT)
-+ ka->sa.sa_handler = SIG_DFL;
-+
-+ if (!(ka->sa.sa_flags & SA_NODEFER)) {
-+ spin_lock_irq(¤t->sigmask_lock);
-+ sigorsets(¤t->blocked, ¤t->blocked,
-+ &ka->sa.sa_mask);
-+ sigaddset(¤t->blocked, signr);
-+ recalc_sigpending(current);
-+ spin_unlock_irq(¤t->sigmask_lock);
-+ }
-+
-+ sp = PT_REGS_SP(regs);
-+
-+ if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
-+ sp = current->sas_ss_sp + current->sas_ss_size;
-+
-+ if(error != 0) PT_REGS_SET_SYSCALL_RETURN(regs, ret);
-+
-+ if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer;
-+ else restorer = NULL;
-+
-+ if(ka->sa.sa_flags & SA_SIGINFO)
-+ err = setup_signal_stack_si(sp, signr, (unsigned long) handler,
-+ restorer, regs, info, &save);
-+ else
-+ err = setup_signal_stack_sc(sp, signr, (unsigned long) handler,
-+ restorer, regs, &save);
-+ if(err) goto segv;
-+
-+ return(0);
-+ segv:
-+ force_segv(signr);
-+ return(1);
-+}
-+
-+/*
-+ * Note that 'init' is a special process: it doesn't get signals it doesn't
-+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
-+ * mistake.
-+ */
-+
-+static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset, int error)
-+{
-+ siginfo_t info;
-+ struct k_sigaction *ka;
-+ int err;
-+
-+ if (!oldset)
-+ oldset = ¤t->blocked;
-+
-+ for (;;) {
-+ unsigned long signr;
-+
-+ spin_lock_irq(¤t->sigmask_lock);
-+ signr = dequeue_signal(¤t->blocked, &info);
-+ spin_unlock_irq(¤t->sigmask_lock);
-+
-+ if (!signr)
-+ break;
-+
-+ if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
-+ /* Let the debugger run. */
-+ current->exit_code = signr;
-+ current->state = TASK_STOPPED;
-+ notify_parent(current, SIGCHLD);
-+ schedule();
-+
-+ /* We're back. Did the debugger cancel the sig? */
-+ signr = current->exit_code;
-+ if (!signr)
-+ continue;
-+ current->exit_code = 0;
-+
-+ /* The debugger continued. Ignore SIGSTOP. */
-+ if (signr == SIGSTOP)
-+ continue;
-+
-+ /* Update the siginfo structure. Is this good? */
-+ if (signr != info.si_signo) {
-+ info.si_signo = signr;
-+ info.si_errno = 0;
-+ info.si_code = SI_USER;
-+ info.si_pid = current->p_pptr->pid;
-+ info.si_uid = current->p_pptr->uid;
-+ }
-+
-+ /* If the (new) signal is now blocked, requeue it. */
-+ if (sigismember(¤t->blocked, signr)) {
-+ send_sig_info(signr, &info, current);
-+ continue;
-+ }
-+ }
-+
-+ ka = ¤t->sig->action[signr-1];
-+ if (ka->sa.sa_handler == SIG_IGN) {
-+ if (signr != SIGCHLD)
-+ continue;
-+ /* Check for SIGCHLD: it's special. */
-+ while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
-+ /* nothing */;
-+ continue;
-+ }
-+
-+ if (ka->sa.sa_handler == SIG_DFL) {
-+ int exit_code = signr;
-+
-+ /* Init gets no signals it doesn't want. */
-+ if (current->pid == 1)
-+ continue;
-+
-+ switch (signr) {
-+ case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG:
-+ continue;
-+
-+ case SIGTSTP: case SIGTTIN: case SIGTTOU:
-+ if (is_orphaned_pgrp(current->pgrp))
-+ continue;
-+ /* FALLTHRU */
-+
-+ case SIGSTOP: {
-+ struct signal_struct *sig;
-+ current->state = TASK_STOPPED;
-+ current->exit_code = signr;
-+ sig = current->p_pptr->sig;
-+ if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
-+ notify_parent(current, SIGCHLD);
-+ schedule();
-+ continue;
-+ }
-+ case SIGQUIT: case SIGILL: case SIGTRAP:
-+ case SIGABRT: case SIGFPE: case SIGSEGV:
-+ case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
-+ if (do_coredump(signr, ¤t->thread.regs))
-+ exit_code |= 0x80;
-+ /* FALLTHRU */
-+
-+ default:
-+ sig_exit(signr, exit_code, &info);
-+ /* NOTREACHED */
-+ }
-+ }
-+
-+ /* Whee! Actually deliver the signal. */
-+ err = handle_signal(regs, signr, ka, &info, oldset, error);
-+ if(!err) return(1);
-+ }
-+
-+ /* Did we come from a system call? */
-+ if(PT_REGS_SYSCALL_NR(regs) >= 0){
-+ /* Restart the system call - no handlers present */
-+ if(PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOHAND ||
-+ PT_REGS_SYSCALL_RET(regs) == -ERESTARTSYS ||
-+ PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOINTR){
-+ PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
-+ PT_REGS_RESTART_SYSCALL(regs);
-+ }
-+ }
-+
-+ /* This closes a way to execute a system call on the host. If
-+ * you set a breakpoint on a system call instruction and singlestep
-+ * from it, the tracing thread used to PTRACE_SINGLESTEP the process
-+ * rather than PTRACE_SYSCALL it, allowing the system call to execute
-+ * on the host. The tracing thread will check this flag and
-+ * PTRACE_SYSCALL if necessary.
-+ */
-+ if((current->ptrace & PT_DTRACE) &&
-+ is_syscall(PT_REGS_IP(¤t->thread.regs)))
-+ (void) CHOOSE_MODE(current->thread.mode.tt.singlestep_syscall = 1, 0);
-+
-+ return(0);
-+}
-+
-+int do_signal(int error)
-+{
-+ return(kern_do_signal(¤t->thread.regs, NULL, error));
-+}
-+
-+/*
-+ * Atomically swap in the new signal mask, and wait for a signal.
-+ */
-+int sys_sigsuspend(int history0, int history1, old_sigset_t mask)
-+{
-+ sigset_t saveset;
-+
-+ mask &= _BLOCKABLE;
-+ spin_lock_irq(¤t->sigmask_lock);
-+ saveset = current->blocked;
-+ siginitset(¤t->blocked, mask);
-+ recalc_sigpending(current);
-+ spin_unlock_irq(¤t->sigmask_lock);
-+
-+ while (1) {
-+ current->state = TASK_INTERRUPTIBLE;
-+ schedule();
-+ if(kern_do_signal(¤t->thread.regs, &saveset, -EINTR))
-+ return(-EINTR);
-+ }
-+}
-+
-+int sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize)
-+{
-+ sigset_t saveset, newset;
-+
-+ /* XXX: Don't preclude handling different sized sigset_t's. */
-+ if (sigsetsize != sizeof(sigset_t))
-+ return -EINVAL;
-+
-+ if (copy_from_user(&newset, unewset, sizeof(newset)))
-+ return -EFAULT;
-+ sigdelsetmask(&newset, ~_BLOCKABLE);
-+
-+ spin_lock_irq(¤t->sigmask_lock);
-+ saveset = current->blocked;
-+ current->blocked = newset;
-+ recalc_sigpending(current);
-+ spin_unlock_irq(¤t->sigmask_lock);
-+
-+ while (1) {
-+ current->state = TASK_INTERRUPTIBLE;
-+ schedule();
-+ if (kern_do_signal(¤t->thread.regs, &saveset, -EINTR))
-+ return(-EINTR);
-+ }
-+}
-+
-+extern int userspace_pid[];
-+
-+static int copy_sc_from_user(struct pt_regs *to, void *from,
-+ struct arch_frame_data *arch)
-+{
-+ int ret;
-+
-+ ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, arch),
-+ copy_sc_from_user_skas(userspace_pid[0],
-+ &to->regs, from));
-+ return(ret);
-+}
-+
-+int sys_sigreturn(struct pt_regs regs)
-+{
-+ void *sc = sp_to_sc(PT_REGS_SP(¤t->thread.regs));
-+ void *mask = sp_to_mask(PT_REGS_SP(¤t->thread.regs));
-+ int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
-+
-+ spin_lock_irq(¤t->sigmask_lock);
-+ copy_from_user(¤t->blocked.sig[0], sc_sigmask(sc),
-+ sizeof(current->blocked.sig[0]));
-+ copy_from_user(¤t->blocked.sig[1], mask, sig_size);
-+ sigdelsetmask(¤t->blocked, ~_BLOCKABLE);
-+ recalc_sigpending(current);
-+ spin_unlock_irq(¤t->sigmask_lock);
-+ copy_sc_from_user(¤t->thread.regs, sc,
-+ &signal_frame_sc.common.arch);
-+ return(PT_REGS_SYSCALL_RET(¤t->thread.regs));
-+}
-+
-+int sys_rt_sigreturn(struct pt_regs regs)
-+{
-+ struct ucontext *uc = sp_to_uc(PT_REGS_SP(¤t->thread.regs));
-+ int sig_size = _NSIG_WORDS * sizeof(unsigned long);
-+
-+ spin_lock_irq(¤t->sigmask_lock);
-+ copy_from_user(¤t->blocked, &uc->uc_sigmask, sig_size);
-+ sigdelsetmask(¤t->blocked, ~_BLOCKABLE);
-+ recalc_sigpending(current);
-+ spin_unlock_irq(¤t->sigmask_lock);
-+ copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext,
-+ &signal_frame_si.common.arch);
-+ return(PT_REGS_SYSCALL_RET(¤t->thread.regs));
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/signal_user.c um/arch/um/kernel/signal_user.c
---- orig/arch/um/kernel/signal_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/signal_user.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,142 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdio.h>
-+#include <unistd.h>
-+#include <stdlib.h>
-+#include <signal.h>
-+#include <errno.h>
-+#include <stdarg.h>
-+#include <string.h>
-+#include <sys/mman.h>
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "user.h"
-+#include "signal_user.h"
-+#include "signal_kern.h"
-+#include "sysdep/sigcontext.h"
-+#include "sigcontext.h"
-+
-+void set_sigstack(void *sig_stack, int size)
-+{
-+ stack_t stack = ((stack_t) { .ss_flags = 0,
-+ .ss_sp = (__ptr_t) sig_stack,
-+ .ss_size = size - sizeof(void *) });
-+
-+ if(sigaltstack(&stack, NULL) != 0)
-+ panic("enabling signal stack failed, errno = %d\n", errno);
-+}
-+
-+void set_handler(int sig, void (*handler)(int), int flags, ...)
-+{
-+ struct sigaction action;
-+ va_list ap;
-+ int mask;
-+
-+ va_start(ap, flags);
-+ action.sa_handler = handler;
-+ sigemptyset(&action.sa_mask);
-+ while((mask = va_arg(ap, int)) != -1){
-+ sigaddset(&action.sa_mask, mask);
-+ }
-+ action.sa_flags = flags;
-+ action.sa_restorer = NULL;
-+ if(sigaction(sig, &action, NULL) < 0)
-+ panic("sigaction failed");
-+}
-+
-+int change_sig(int signal, int on)
-+{
-+ sigset_t sigset, old;
-+
-+ sigemptyset(&sigset);
-+ sigaddset(&sigset, signal);
-+ sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old);
-+ return(!sigismember(&old, signal));
-+}
-+
-+static void change_signals(int type)
-+{
-+ sigset_t mask;
-+
-+ sigemptyset(&mask);
-+ sigaddset(&mask, SIGVTALRM);
-+ sigaddset(&mask, SIGALRM);
-+ sigaddset(&mask, SIGIO);
-+ sigaddset(&mask, SIGPROF);
-+ if(sigprocmask(type, &mask, NULL) < 0)
-+ panic("Failed to change signal mask - errno = %d", errno);
-+}
-+
-+void block_signals(void)
-+{
-+ change_signals(SIG_BLOCK);
-+}
-+
-+void unblock_signals(void)
-+{
-+ change_signals(SIG_UNBLOCK);
-+}
-+
-+#define SIGIO_BIT 0
-+#define SIGVTALRM_BIT 1
-+
-+static int enable_mask(sigset_t *mask)
-+{
-+ int sigs;
-+
-+ sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT;
-+ sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT;
-+ sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT;
-+ return(sigs);
-+}
-+
-+int get_signals(void)
-+{
-+ sigset_t mask;
-+
-+ if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0)
-+ panic("Failed to get signal mask");
-+ return(enable_mask(&mask));
-+}
-+
-+int set_signals(int enable)
-+{
-+ sigset_t mask;
-+ int ret;
-+
-+ sigemptyset(&mask);
-+ if(enable & (1 << SIGIO_BIT))
-+ sigaddset(&mask, SIGIO);
-+ if(enable & (1 << SIGVTALRM_BIT)){
-+ sigaddset(&mask, SIGVTALRM);
-+ sigaddset(&mask, SIGALRM);
-+ }
-+ if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
-+ panic("Failed to enable signals");
-+ ret = enable_mask(&mask);
-+ sigemptyset(&mask);
-+ if((enable & (1 << SIGIO_BIT)) == 0)
-+ sigaddset(&mask, SIGIO);
-+ if((enable & (1 << SIGVTALRM_BIT)) == 0){
-+ sigaddset(&mask, SIGVTALRM);
-+ sigaddset(&mask, SIGALRM);
-+ }
-+ if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0)
-+ panic("Failed to block signals");
-+
-+ return(ret);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/exec_kern.c um/arch/um/kernel/skas/exec_kern.c
---- orig/arch/um/kernel/skas/exec_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/exec_kern.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,41 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/kernel.h"
-+#include "asm/current.h"
-+#include "asm/page.h"
-+#include "asm/signal.h"
-+#include "asm/ptrace.h"
-+#include "asm/uaccess.h"
-+#include "asm/mmu_context.h"
-+#include "tlb.h"
-+#include "skas.h"
-+#include "mmu.h"
-+#include "os.h"
-+
-+void flush_thread_skas(void)
-+{
-+ force_flush_all();
-+ switch_mm_skas(current->mm->context.skas.mm_fd);
-+}
-+
-+void start_thread_skas(struct pt_regs *regs, unsigned long eip,
-+ unsigned long esp)
-+{
-+ set_fs(USER_DS);
-+ PT_REGS_IP(regs) = eip;
-+ PT_REGS_SP(regs) = esp;
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/exec_user.c um/arch/um/kernel/skas/exec_user.c
---- orig/arch/um/kernel/skas/exec_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/exec_user.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,61 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdlib.h>
-+#include <errno.h>
-+#include <signal.h>
-+#include <sched.h>
-+#include <sys/wait.h>
-+#include <sys/ptrace.h>
-+#include "user.h"
-+#include "kern_util.h"
-+#include "os.h"
-+#include "time_user.h"
-+
-+static int user_thread_tramp(void *arg)
-+{
-+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
-+ panic("user_thread_tramp - PTRACE_TRACEME failed, "
-+ "errno = %d\n", errno);
-+ enable_timer();
-+ os_stop_process(os_getpid());
-+ return(0);
-+}
-+
-+int user_thread(unsigned long stack, int flags)
-+{
-+ int pid, status;
-+
-+ pid = clone(user_thread_tramp, (void *) stack_sp(stack),
-+ flags | CLONE_FILES | SIGCHLD, NULL);
-+ if(pid < 0){
-+ printk("user_thread - clone failed, errno = %d\n", errno);
-+ return(pid);
-+ }
-+
-+ if(waitpid(pid, &status, WUNTRACED) < 0){
-+ printk("user_thread - waitpid failed, errno = %d\n", errno);
-+ return(-errno);
-+ }
-+
-+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)){
-+ printk("user_thread - trampoline didn't stop, status = %d\n",
-+ status);
-+ return(-EINVAL);
-+ }
-+
-+ return(pid);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/include/mmu.h um/arch/um/kernel/skas/include/mmu.h
---- orig/arch/um/kernel/skas/include/mmu.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/include/mmu.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,27 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __SKAS_MMU_H
-+#define __SKAS_MMU_H
-+
-+#include "linux/list.h"
-+#include "linux/spinlock.h"
-+
-+struct mmu_context_skas {
-+ int mm_fd;
-+};
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/include/mode.h um/arch/um/kernel/skas/include/mode.h
---- orig/arch/um/kernel/skas/include/mode.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/include/mode.h 2003-11-19 03:27:36.000000000 -0500
-@@ -0,0 +1,37 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __MODE_SKAS_H__
-+#define __MODE_SKAS_H__
-+
-+extern unsigned long exec_regs[];
-+extern unsigned long exec_fp_regs[];
-+extern unsigned long exec_fpx_regs[];
-+extern int have_fpx_regs;
-+
-+extern void user_time_init_skas(void);
-+extern int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs,
-+ void *from_ptr);
-+extern int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp,
-+ union uml_pt_regs *regs,
-+ unsigned long fault_addr, int fault_type);
-+extern void sig_handler_common_skas(int sig, void *sc_ptr);
-+extern void halt_skas(void);
-+extern void reboot_skas(void);
-+extern void kill_off_processes_skas(void);
-+extern int is_skas_winch(int pid, int fd, void *data);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/include/mode_kern.h um/arch/um/kernel/skas/include/mode_kern.h
---- orig/arch/um/kernel/skas/include/mode_kern.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/include/mode_kern.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,51 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __SKAS_MODE_KERN_H__
-+#define __SKAS_MODE_KERN_H__
-+
-+#include "linux/sched.h"
-+#include "asm/page.h"
-+#include "asm/ptrace.h"
-+
-+extern void flush_thread_skas(void);
-+extern void *_switch_to_skas(void *prev, void *next);
-+extern void start_thread_skas(struct pt_regs *regs, unsigned long eip,
-+ unsigned long esp);
-+extern int copy_thread_skas(int nr, unsigned long clone_flags,
-+ unsigned long sp, unsigned long stack_top,
-+ struct task_struct *p, struct pt_regs *regs);
-+extern void release_thread_skas(struct task_struct *task);
-+extern void exit_thread_skas(void);
-+extern void initial_thread_cb_skas(void (*proc)(void *), void *arg);
-+extern void init_idle_skas(void);
-+extern void flush_tlb_kernel_vm_skas(void);
-+extern void __flush_tlb_one_skas(unsigned long addr);
-+extern void flush_tlb_range_skas(struct mm_struct *mm, unsigned long start,
-+ unsigned long end);
-+extern void flush_tlb_mm_skas(struct mm_struct *mm);
-+extern void force_flush_all_skas(void);
-+extern long execute_syscall_skas(void *r);
-+extern void before_mem_skas(unsigned long unused);
-+extern unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out,
-+ unsigned long *task_size_out);
-+extern int start_uml_skas(void);
-+extern int external_pid_skas(struct task_struct *task);
-+extern int thread_pid_skas(struct thread_struct *thread);
-+
-+#define kmem_end_skas (host_task_size - 1024 * 1024)
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/include/proc_mm.h um/arch/um/kernel/skas/include/proc_mm.h
---- orig/arch/um/kernel/skas/include/proc_mm.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/include/proc_mm.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,55 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __SKAS_PROC_MM_H
-+#define __SKAS_PROC_MM_H
-+
-+#define MM_MMAP 54
-+#define MM_MUNMAP 55
-+#define MM_MPROTECT 56
-+#define MM_COPY_SEGMENTS 57
-+
-+struct mm_mmap {
-+ unsigned long addr;
-+ unsigned long len;
-+ unsigned long prot;
-+ unsigned long flags;
-+ unsigned long fd;
-+ unsigned long offset;
-+};
-+
-+struct mm_munmap {
-+ unsigned long addr;
-+ unsigned long len;
-+};
-+
-+struct mm_mprotect {
-+ unsigned long addr;
-+ unsigned long len;
-+ unsigned int prot;
-+};
-+
-+struct proc_mm_op {
-+ int op;
-+ union {
-+ struct mm_mmap mmap;
-+ struct mm_munmap munmap;
-+ struct mm_mprotect mprotect;
-+ int copy_segments;
-+ } u;
-+};
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/include/ptrace-skas.h um/arch/um/kernel/skas/include/ptrace-skas.h
---- orig/arch/um/kernel/skas/include/ptrace-skas.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/include/ptrace-skas.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,57 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __PTRACE_SKAS_H
-+#define __PTRACE_SKAS_H
-+
-+#include "uml-config.h"
-+
-+#ifdef UML_CONFIG_MODE_SKAS
-+
-+#include "skas_ptregs.h"
-+
-+#define HOST_FRAME_SIZE 17
-+
-+#define REGS_IP(r) ((r)[HOST_IP])
-+#define REGS_SP(r) ((r)[HOST_SP])
-+#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS])
-+#define REGS_EAX(r) ((r)[HOST_EAX])
-+#define REGS_EBX(r) ((r)[HOST_EBX])
-+#define REGS_ECX(r) ((r)[HOST_ECX])
-+#define REGS_EDX(r) ((r)[HOST_EDX])
-+#define REGS_ESI(r) ((r)[HOST_ESI])
-+#define REGS_EDI(r) ((r)[HOST_EDI])
-+#define REGS_EBP(r) ((r)[HOST_EBP])
-+#define REGS_CS(r) ((r)[HOST_CS])
-+#define REGS_SS(r) ((r)[HOST_SS])
-+#define REGS_DS(r) ((r)[HOST_DS])
-+#define REGS_ES(r) ((r)[HOST_ES])
-+#define REGS_FS(r) ((r)[HOST_FS])
-+#define REGS_GS(r) ((r)[HOST_GS])
-+
-+#define REGS_SET_SYSCALL_RETURN(r, res) REGS_EAX(r) = (res)
-+
-+#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
-+
-+#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type)
-+
-+#define REGS_FAULT_ADDR(r) ((r)->fault_addr)
-+
-+#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type)
-+
-+#endif
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/include/skas.h um/arch/um/kernel/skas/include/skas.h
---- orig/arch/um/kernel/skas/include/skas.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/include/skas.h 2003-11-19 03:00:51.000000000 -0500
-@@ -0,0 +1,49 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __SKAS_H
-+#define __SKAS_H
-+
-+#include "sysdep/ptrace.h"
-+
-+extern int userspace_pid[];
-+
-+extern void switch_threads(void *me, void *next);
-+extern void thread_wait(void *sw, void *fb);
-+extern void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
-+ void (*handler)(int));
-+extern int start_idle_thread(void *stack, void *switch_buf_ptr,
-+ void **fork_buf_ptr);
-+extern int user_thread(unsigned long stack, int flags);
-+extern void userspace(union uml_pt_regs *regs);
-+extern void new_thread_proc(void *stack, void (*handler)(int sig));
-+extern void remove_sigstack(void);
-+extern void new_thread_handler(int sig);
-+extern void handle_syscall(union uml_pt_regs *regs);
-+extern void map(int fd, unsigned long virt, unsigned long phys,
-+ unsigned long len, int r, int w, int x);
-+extern int unmap(int fd, void *addr, int len);
-+extern int protect(int fd, unsigned long addr, unsigned long len,
-+ int r, int w, int x, int must_succeed);
-+extern void user_signal(int sig, union uml_pt_regs *regs);
-+extern int singlestepping_skas(void);
-+extern int new_mm(int from);
-+extern void save_registers(union uml_pt_regs *regs);
-+extern void restore_registers(union uml_pt_regs *regs);
-+extern void start_userspace(int cpu);
-+extern void init_registers(int pid);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/include/uaccess.h um/arch/um/kernel/skas/include/uaccess.h
---- orig/arch/um/kernel/skas/include/uaccess.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/include/uaccess.h 2004-01-17 06:35:41.000000000 -0500
-@@ -0,0 +1,40 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __SKAS_UACCESS_H
-+#define __SKAS_UACCESS_H
-+
-+#include "asm/errno.h"
-+
-+#define access_ok_skas(type, addr, size) \
-+ ((segment_eq(get_fs(), KERNEL_DS)) || \
-+ (((unsigned long) (addr) < TASK_SIZE) && \
-+ ((unsigned long) (addr) + (size) <= TASK_SIZE)))
-+
-+static inline int verify_area_skas(int type, const void * addr,
-+ unsigned long size)
-+{
-+ return(access_ok_skas(type, addr, size) ? 0 : -EFAULT);
-+}
-+
-+extern int copy_from_user_skas(void *to, const void *from, int n);
-+extern int copy_to_user_skas(void *to, const void *from, int n);
-+extern int strncpy_from_user_skas(char *dst, const char *src, int count);
-+extern int __clear_user_skas(void *mem, int len);
-+extern int clear_user_skas(void *mem, int len);
-+extern int strnlen_user_skas(const void *str, int len);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/Makefile um/arch/um/kernel/skas/Makefile
---- orig/arch/um/kernel/skas/Makefile 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/Makefile 2003-11-11 06:36:12.000000000 -0500
-@@ -0,0 +1,31 @@
-+#
-+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+# Licensed under the GPL
-+#
-+
-+O_TARGET = skas.o
-+
-+obj-y = exec_kern.o exec_user.o mem.o mem_user.o mmu.o process.o \
-+ process_kern.o syscall_kern.o syscall_user.o time.o tlb.o trap_user.o \
-+ uaccess.o
-+
-+subdir-y = sys-$(SUBARCH)
-+
-+obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
-+
-+USER_OBJS = $(filter %_user.o,$(obj-y)) process.o time.o
-+
-+include $(TOPDIR)/Rules.make
-+
-+include/skas_ptregs.h : util/mk_ptregs
-+ util/mk_ptregs > $@
-+
-+util/mk_ptregs :
-+ $(MAKE) -C util
-+
-+$(USER_OBJS) : %.o: %.c
-+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $<
-+
-+clean :
-+ $(MAKE) -C util clean
-+ $(RM) -f include/skas_ptregs.h
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/mem.c um/arch/um/kernel/skas/mem.c
---- orig/arch/um/kernel/skas/mem.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/mem.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,30 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/config.h"
-+#include "linux/mm.h"
-+#include "mem_user.h"
-+
-+unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out,
-+ unsigned long *task_size_out)
-+{
-+ /* Round up to the nearest 4M */
-+ unsigned long top = ROUND_4M((unsigned long) &arg);
-+
-+ *host_size_out = top;
-+ *task_size_out = top;
-+ return(((unsigned long) set_task_sizes_skas) & ~0xffffff);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/mem_user.c um/arch/um/kernel/skas/mem_user.c
---- orig/arch/um/kernel/skas/mem_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/mem_user.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,105 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <errno.h>
-+#include <sys/mman.h>
-+#include <sys/ptrace.h>
-+#include "mem_user.h"
-+#include "mem.h"
-+#include "user.h"
-+#include "os.h"
-+#include "proc_mm.h"
-+
-+void map(int fd, unsigned long virt, unsigned long phys, unsigned long len,
-+ int r, int w, int x)
-+{
-+ struct proc_mm_op map;
-+ __u64 offset;
-+ int prot, n, phys_fd;
-+
-+ prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
-+ (x ? PROT_EXEC : 0);
-+ phys_fd = phys_mapping(phys, &offset);
-+
-+ map = ((struct proc_mm_op) { .op = MM_MMAP,
-+ .u =
-+ { .mmap =
-+ { .addr = virt,
-+ .len = len,
-+ .prot = prot,
-+ .flags = MAP_SHARED |
-+ MAP_FIXED,
-+ .fd = phys_fd,
-+ .offset = offset
-+ } } } );
-+ n = os_write_file(fd, &map, sizeof(map));
-+ if(n != sizeof(map))
-+ printk("map : /proc/mm map failed, err = %d\n", -n);
-+}
-+
-+int unmap(int fd, void *addr, int len)
-+{
-+ struct proc_mm_op unmap;
-+ int n;
-+
-+ unmap = ((struct proc_mm_op) { .op = MM_MUNMAP,
-+ .u =
-+ { .munmap =
-+ { .addr = (unsigned long) addr,
-+ .len = len } } } );
-+ n = os_write_file(fd, &unmap, sizeof(unmap));
-+ if(n != sizeof(unmap)) {
-+ if(n < 0)
-+ return(n);
-+ else if(n > 0)
-+ return(-EIO);
-+ }
-+
-+ return(0);
-+}
-+
-+int protect(int fd, unsigned long addr, unsigned long len, int r, int w,
-+ int x, int must_succeed)
-+{
-+ struct proc_mm_op protect;
-+ int prot, n;
-+
-+ prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
-+ (x ? PROT_EXEC : 0);
-+
-+ protect = ((struct proc_mm_op) { .op = MM_MPROTECT,
-+ .u =
-+ { .mprotect =
-+ { .addr = (unsigned long) addr,
-+ .len = len,
-+ .prot = prot } } } );
-+
-+ n = os_write_file(fd, &protect, sizeof(protect));
-+ if(n != sizeof(protect)) {
-+ if(n == 0) return(0);
-+
-+ if(must_succeed)
-+ panic("protect failed, err = %d", -n);
-+
-+ return(-EIO);
-+ }
-+
-+ return(0);
-+}
-+
-+void before_mem_skas(unsigned long unused)
-+{
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/mmu.c um/arch/um/kernel/skas/mmu.c
---- orig/arch/um/kernel/skas/mmu.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/mmu.c 2003-11-15 22:25:20.000000000 -0500
-@@ -0,0 +1,46 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/list.h"
-+#include "linux/spinlock.h"
-+#include "linux/slab.h"
-+#include "asm/segment.h"
-+#include "asm/mmu.h"
-+#include "os.h"
-+#include "skas.h"
-+
-+int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
-+{
-+ int from;
-+
-+ if((current->mm != NULL) && (current->mm != &init_mm))
-+ from = current->mm->context.skas.mm_fd;
-+ else from = -1;
-+
-+ mm->context.skas.mm_fd = new_mm(from);
-+ if(mm->context.skas.mm_fd < 0){
-+ printk("init_new_context_skas - new_mm failed, errno = %d\n",
-+ mm->context.skas.mm_fd);
-+ return(mm->context.skas.mm_fd);
-+ }
-+
-+ return(0);
-+}
-+
-+void destroy_context_skas(struct mm_struct *mm)
-+{
-+ os_close_file(mm->context.skas.mm_fd);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/process.c um/arch/um/kernel/skas/process.c
---- orig/arch/um/kernel/skas/process.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/process.c 2004-01-31 02:49:36.000000000 -0500
-@@ -0,0 +1,417 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <errno.h>
-+#include <signal.h>
-+#include <setjmp.h>
-+#include <sched.h>
-+#include <sys/wait.h>
-+#include <sys/ptrace.h>
-+#include <sys/mman.h>
-+#include <sys/user.h>
-+#include <asm/unistd.h>
-+#include "user.h"
-+#include "ptrace_user.h"
-+#include "time_user.h"
-+#include "sysdep/ptrace.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "skas.h"
-+#include "sysdep/sigcontext.h"
-+#include "os.h"
-+#include "proc_mm.h"
-+#include "skas_ptrace.h"
-+#include "chan_user.h"
-+
-+int is_skas_winch(int pid, int fd, void *data)
-+{
-+ if(pid != getpid())
-+ return(0);
-+
-+ register_winch_irq(-1, fd, -1, data);
-+ return(1);
-+}
-+
-+/* These are set once at boot time and not changed thereafter */
-+
-+unsigned long exec_regs[FRAME_SIZE];
-+unsigned long exec_fp_regs[HOST_FP_SIZE];
-+unsigned long exec_fpx_regs[HOST_XFP_SIZE];
-+int have_fpx_regs = 1;
-+
-+static void handle_segv(int pid)
-+{
-+ struct ptrace_faultinfo fault;
-+ int err;
-+
-+ err = ptrace(PTRACE_FAULTINFO, pid, 0, &fault);
-+ if(err)
-+ panic("handle_segv - PTRACE_FAULTINFO failed, errno = %d\n",
-+ errno);
-+
-+ segv(fault.addr, 0, FAULT_WRITE(fault.is_write), 1, NULL);
-+}
-+
-+static void handle_trap(int pid, union uml_pt_regs *regs)
-+{
-+ int err, syscall_nr, status;
-+
-+ syscall_nr = PT_SYSCALL_NR(regs->skas.regs);
-+ UPT_SYSCALL_NR(regs) = syscall_nr;
-+ if(syscall_nr < 1){
-+ relay_signal(SIGTRAP, regs);
-+ return;
-+ }
-+
-+ err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
-+ if(err < 0)
-+ panic("handle_trap - nullifying syscall failed errno = %d\n",
-+ errno);
-+
-+ err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
-+ if(err < 0)
-+ panic("handle_trap - continuing to end of syscall failed, "
-+ "errno = %d\n", errno);
-+
-+ err = waitpid(pid, &status, WUNTRACED);
-+ if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
-+ panic("handle_trap - failed to wait at end of syscall, "
-+ "errno = %d, status = %d\n", errno, status);
-+
-+ handle_syscall(regs);
-+}
-+
-+static int userspace_tramp(void *arg)
-+{
-+ init_new_thread_signals(0);
-+ enable_timer();
-+ ptrace(PTRACE_TRACEME, 0, 0, 0);
-+ os_stop_process(os_getpid());
-+ return(0);
-+}
-+
-+/* Each element set once, and only accessed by a single processor anyway */
-+#define NR_CPUS 1
-+int userspace_pid[NR_CPUS];
-+
-+void start_userspace(int cpu)
-+{
-+ void *stack;
-+ unsigned long sp;
-+ int pid, status, n;
-+
-+ stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
-+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-+ if(stack == MAP_FAILED)
-+ panic("start_userspace : mmap failed, errno = %d", errno);
-+ sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
-+
-+ pid = clone(userspace_tramp, (void *) sp,
-+ CLONE_FILES | CLONE_VM | SIGCHLD, NULL);
-+ if(pid < 0)
-+ panic("start_userspace : clone failed, errno = %d", errno);
-+
-+ do {
-+ n = waitpid(pid, &status, WUNTRACED);
-+ if(n < 0)
-+ panic("start_userspace : wait failed, errno = %d",
-+ errno);
-+ } while(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM));
-+
-+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
-+ panic("start_userspace : expected SIGSTOP, got status = %d",
-+ status);
-+
-+ if(munmap(stack, PAGE_SIZE) < 0)
-+ panic("start_userspace : munmap failed, errno = %d\n", errno);
-+
-+ userspace_pid[cpu] = pid;
-+}
-+
-+void userspace(union uml_pt_regs *regs)
-+{
-+ int err, status, op, pid = userspace_pid[0];
-+
-+ restore_registers(regs);
-+
-+ err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
-+ if(err)
-+ panic("userspace - PTRACE_SYSCALL failed, errno = %d\n",
-+ errno);
-+ while(1){
-+ err = waitpid(pid, &status, WUNTRACED);
-+ if(err < 0)
-+ panic("userspace - waitpid failed, errno = %d\n",
-+ errno);
-+
-+ regs->skas.is_user = 1;
-+ save_registers(regs);
-+
-+ if(WIFSTOPPED(status)){
-+ switch(WSTOPSIG(status)){
-+ case SIGSEGV:
-+ handle_segv(pid);
-+ break;
-+ case SIGTRAP:
-+ handle_trap(pid, regs);
-+ break;
-+ case SIGIO:
-+ case SIGVTALRM:
-+ case SIGILL:
-+ case SIGBUS:
-+ case SIGFPE:
-+ case SIGWINCH:
-+ user_signal(WSTOPSIG(status), regs);
-+ break;
-+ default:
-+ printk("userspace - child stopped with signal "
-+ "%d\n", WSTOPSIG(status));
-+ }
-+ interrupt_end();
-+ }
-+
-+ restore_registers(regs);
-+
-+ op = singlestepping_skas() ? PTRACE_SINGLESTEP :
-+ PTRACE_SYSCALL;
-+ err = ptrace(op, pid, 0, 0);
-+ if(err)
-+ panic("userspace - PTRACE_SYSCALL failed, "
-+ "errno = %d\n", errno);
-+ }
-+}
-+
-+void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
-+ void (*handler)(int))
-+{
-+ sigjmp_buf switch_buf, fork_buf;
-+
-+ *switch_buf_ptr = &switch_buf;
-+ *fork_buf_ptr = &fork_buf;
-+
-+ if(sigsetjmp(fork_buf, 1) == 0)
-+ new_thread_proc(stack, handler);
-+
-+ remove_sigstack();
-+}
-+
-+void thread_wait(void *sw, void *fb)
-+{
-+ sigjmp_buf buf, **switch_buf = sw, *fork_buf;
-+
-+ *switch_buf = &buf;
-+ fork_buf = fb;
-+ if(sigsetjmp(buf, 1) == 0)
-+ siglongjmp(*fork_buf, 1);
-+}
-+
-+static int move_registers(int pid, int int_op, int fp_op,
-+ union uml_pt_regs *regs, unsigned long *fp_regs)
-+{
-+ if(ptrace(int_op, pid, 0, regs->skas.regs) < 0)
-+ return(-errno);
-+ if(ptrace(fp_op, pid, 0, fp_regs) < 0)
-+ return(-errno);
-+ return(0);
-+}
-+
-+void save_registers(union uml_pt_regs *regs)
-+{
-+ unsigned long *fp_regs;
-+ int err, fp_op;
-+
-+ if(have_fpx_regs){
-+ fp_op = PTRACE_GETFPXREGS;
-+ fp_regs = regs->skas.xfp;
-+ }
-+ else {
-+ fp_op = PTRACE_GETFPREGS;
-+ fp_regs = regs->skas.fp;
-+ }
-+
-+ err = move_registers(userspace_pid[0], PTRACE_GETREGS, fp_op, regs,
-+ fp_regs);
-+ if(err)
-+ panic("save_registers - saving registers failed, errno = %d\n",
-+ -err);
-+}
-+
-+void restore_registers(union uml_pt_regs *regs)
-+{
-+ unsigned long *fp_regs;
-+ int err, fp_op;
-+
-+ if(have_fpx_regs){
-+ fp_op = PTRACE_SETFPXREGS;
-+ fp_regs = regs->skas.xfp;
-+ }
-+ else {
-+ fp_op = PTRACE_SETFPREGS;
-+ fp_regs = regs->skas.fp;
-+ }
-+
-+ err = move_registers(userspace_pid[0], PTRACE_SETREGS, fp_op, regs,
-+ fp_regs);
-+ if(err)
-+ panic("restore_registers - saving registers failed, "
-+ "errno = %d\n", -err);
-+}
-+
-+void switch_threads(void *me, void *next)
-+{
-+ sigjmp_buf my_buf, **me_ptr = me, *next_buf = next;
-+
-+ *me_ptr = &my_buf;
-+ if(sigsetjmp(my_buf, 1) == 0)
-+ siglongjmp(*next_buf, 1);
-+}
-+
-+static sigjmp_buf initial_jmpbuf;
-+
-+/* XXX Make these percpu */
-+static void (*cb_proc)(void *arg);
-+static void *cb_arg;
-+static sigjmp_buf *cb_back;
-+
-+int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
-+{
-+ sigjmp_buf **switch_buf = switch_buf_ptr;
-+ int n;
-+
-+ *fork_buf_ptr = &initial_jmpbuf;
-+ n = sigsetjmp(initial_jmpbuf, 1);
-+ if(n == 0)
-+ new_thread_proc((void *) stack, new_thread_handler);
-+ else if(n == 1)
-+ remove_sigstack();
-+ else if(n == 2){
-+ (*cb_proc)(cb_arg);
-+ siglongjmp(*cb_back, 1);
-+ }
-+ else if(n == 3){
-+ kmalloc_ok = 0;
-+ return(0);
-+ }
-+ else if(n == 4){
-+ kmalloc_ok = 0;
-+ return(1);
-+ }
-+ siglongjmp(**switch_buf, 1);
-+}
-+
-+void remove_sigstack(void)
-+{
-+ stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE,
-+ .ss_sp = NULL,
-+ .ss_size = 0 });
-+
-+ if(sigaltstack(&stack, NULL) != 0)
-+ panic("disabling signal stack failed, errno = %d\n", errno);
-+}
-+
-+void initial_thread_cb_skas(void (*proc)(void *), void *arg)
-+{
-+ sigjmp_buf here;
-+
-+ cb_proc = proc;
-+ cb_arg = arg;
-+ cb_back = &here;
-+
-+ block_signals();
-+ if(sigsetjmp(here, 1) == 0)
-+ siglongjmp(initial_jmpbuf, 2);
-+ unblock_signals();
-+
-+ cb_proc = NULL;
-+ cb_arg = NULL;
-+ cb_back = NULL;
-+}
-+
-+void halt_skas(void)
-+{
-+ block_signals();
-+ siglongjmp(initial_jmpbuf, 3);
-+}
-+
-+void reboot_skas(void)
-+{
-+ block_signals();
-+ siglongjmp(initial_jmpbuf, 4);
-+}
-+
-+int new_mm(int from)
-+{
-+ struct proc_mm_op copy;
-+ int n, fd = os_open_file("/proc/mm",
-+ of_cloexec(of_write(OPENFLAGS())), 0);
-+
-+ if(fd < 0)
-+ return(fd);
-+
-+ if(from != -1){
-+ copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS,
-+ .u =
-+ { .copy_segments = from } } );
-+ n = os_write_file(fd, ©, sizeof(copy));
-+ if(n != sizeof(copy))
-+ printk("new_mm : /proc/mm copy_segments failed, "
-+ "err = %d\n", -n);
-+ }
-+
-+ return(fd);
-+}
-+
-+void switch_mm_skas(int mm_fd)
-+{
-+ int err;
-+
-+#warning need cpu pid in switch_mm_skas
-+ err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_fd);
-+ if(err)
-+ panic("switch_mm_skas - PTRACE_SWITCH_MM failed, errno = %d\n",
-+ errno);
-+}
-+
-+void kill_off_processes_skas(void)
-+{
-+#warning need to loop over userspace_pids in kill_off_processes_skas
-+ os_kill_process(userspace_pid[0], 1);
-+}
-+
-+void init_registers(int pid)
-+{
-+ int err;
-+
-+ if(ptrace(PTRACE_GETREGS, pid, 0, exec_regs) < 0)
-+ panic("check_ptrace : PTRACE_GETREGS failed, errno = %d",
-+ errno);
-+
-+ err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs);
-+ if(!err)
-+ return;
-+
-+ have_fpx_regs = 0;
-+ if(errno != EIO)
-+ panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
-+ errno);
-+
-+ err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs);
-+ if(err)
-+ panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d",
-+ errno);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/process_kern.c um/arch/um/kernel/skas/process_kern.c
---- orig/arch/um/kernel/skas/process_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/process_kern.c 2003-11-19 03:18:25.000000000 -0500
-@@ -0,0 +1,196 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/sched.h"
-+#include "linux/slab.h"
-+#include "kern_util.h"
-+#include "time_user.h"
-+#include "signal_user.h"
-+#include "skas.h"
-+#include "os.h"
-+#include "user_util.h"
-+#include "tlb.h"
-+#include "frame.h"
-+#include "kern.h"
-+#include "mode.h"
-+
-+int singlestepping_skas(void)
-+{
-+ int ret = current->ptrace & PT_DTRACE;
-+
-+ current->ptrace &= ~PT_DTRACE;
-+ return(ret);
-+}
-+
-+void *_switch_to_skas(void *prev, void *next)
-+{
-+ struct task_struct *from, *to;
-+
-+ from = prev;
-+ to = next;
-+
-+ /* XXX need to check runqueues[cpu].idle */
-+ if(current->pid == 0)
-+ switch_timers(0);
-+
-+ to->thread.prev_sched = from;
-+ set_current(to);
-+
-+ switch_threads(&from->thread.mode.skas.switch_buf,
-+ to->thread.mode.skas.switch_buf);
-+
-+ if(current->pid == 0)
-+ switch_timers(1);
-+
-+ return(current->thread.prev_sched);
-+}
-+
-+extern void schedule_tail(struct task_struct *prev);
-+
-+void new_thread_handler(int sig)
-+{
-+ int (*fn)(void *), n;
-+ void *arg;
-+
-+ fn = current->thread.request.u.thread.proc;
-+ arg = current->thread.request.u.thread.arg;
-+ change_sig(SIGUSR1, 1);
-+ thread_wait(¤t->thread.mode.skas.switch_buf,
-+ current->thread.mode.skas.fork_buf);
-+
-+ if(current->thread.prev_sched != NULL)
-+ schedule_tail(current->thread.prev_sched);
-+ current->thread.prev_sched = NULL;
-+
-+ /* The return value is 1 if the kernel thread execs a process,
-+ * 0 if it just exits
-+ */
-+ n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf);
-+ if(n == 1)
-+ userspace(¤t->thread.regs.regs);
-+ else do_exit(0);
-+}
-+
-+void new_thread_proc(void *stack, void (*handler)(int sig))
-+{
-+ init_new_thread_stack(stack, handler);
-+ os_usr1_process(os_getpid());
-+}
-+
-+void release_thread_skas(struct task_struct *task)
-+{
-+}
-+
-+void exit_thread_skas(void)
-+{
-+}
-+
-+void fork_handler(int sig)
-+{
-+ change_sig(SIGUSR1, 1);
-+ thread_wait(¤t->thread.mode.skas.switch_buf,
-+ current->thread.mode.skas.fork_buf);
-+
-+ force_flush_all();
-+ if(current->thread.prev_sched != NULL)
-+ schedule_tail(current->thread.prev_sched);
-+ current->thread.prev_sched = NULL;
-+ unblock_signals();
-+
-+ userspace(¤t->thread.regs.regs);
-+}
-+
-+int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
-+ unsigned long stack_top, struct task_struct * p,
-+ struct pt_regs *regs)
-+{
-+ void (*handler)(int);
-+
-+ if(current->thread.forking){
-+ memcpy(&p->thread.regs.regs.skas,
-+ ¤t->thread.regs.regs.skas,
-+ sizeof(p->thread.regs.regs.skas));
-+ REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0);
-+ if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
-+
-+ handler = fork_handler;
-+ }
-+ else {
-+ memcpy(p->thread.regs.regs.skas.regs, exec_regs,
-+ sizeof(p->thread.regs.regs.skas.regs));
-+ memcpy(p->thread.regs.regs.skas.fp, exec_fp_regs,
-+ sizeof(p->thread.regs.regs.skas.fp));
-+ memcpy(p->thread.regs.regs.skas.xfp, exec_fpx_regs,
-+ sizeof(p->thread.regs.regs.skas.xfp));
-+ p->thread.request.u.thread = current->thread.request.u.thread;
-+ handler = new_thread_handler;
-+ }
-+
-+ new_thread((void *) p->thread.kernel_stack,
-+ &p->thread.mode.skas.switch_buf,
-+ &p->thread.mode.skas.fork_buf, handler);
-+ return(0);
-+}
-+
-+void init_idle_skas(void)
-+{
-+ cpu_tasks[current->processor].pid = os_getpid();
-+}
-+
-+extern void start_kernel(void);
-+
-+static int start_kernel_proc(void *unused)
-+{
-+ int pid;
-+
-+ block_signals();
-+ pid = os_getpid();
-+
-+ cpu_tasks[0].pid = pid;
-+ cpu_tasks[0].task = current;
-+#ifdef CONFIG_SMP
-+ cpu_online_map = 1;
-+#endif
-+ start_kernel();
-+ return(0);
-+}
-+
-+int start_uml_skas(void)
-+{
-+ start_userspace(0);
-+ capture_signal_stack();
-+ idle_timer();
-+
-+ init_new_thread_signals(1);
-+
-+ init_task.thread.request.u.thread.proc = start_kernel_proc;
-+ init_task.thread.request.u.thread.arg = NULL;
-+ return(start_idle_thread((void *) init_task.thread.kernel_stack,
-+ &init_task.thread.mode.skas.switch_buf,
-+ &init_task.thread.mode.skas.fork_buf));
-+}
-+
-+int external_pid_skas(struct task_struct *task)
-+{
-+#warning Need to look up userspace_pid by cpu
-+ return(userspace_pid[0]);
-+}
-+
-+int thread_pid_skas(struct thread_struct *thread)
-+{
-+#warning Need to look up userspace_pid by cpu
-+ return(userspace_pid[0]);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/syscall_kern.c um/arch/um/kernel/skas/syscall_kern.c
---- orig/arch/um/kernel/skas/syscall_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/syscall_kern.c 2004-01-04 08:20:29.000000000 -0500
-@@ -0,0 +1,42 @@
-+/*
-+ * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/sys.h"
-+#include "asm/errno.h"
-+#include "asm/unistd.h"
-+#include "asm/ptrace.h"
-+#include "asm/current.h"
-+#include "sysdep/syscalls.h"
-+#include "kern_util.h"
-+
-+extern syscall_handler_t *sys_call_table[];
-+
-+long execute_syscall_skas(void *r)
-+{
-+ struct pt_regs *regs = r;
-+ long res;
-+ int syscall;
-+
-+ current->thread.nsyscalls++;
-+ nsyscalls++;
-+ syscall = UPT_SYSCALL_NR(®s->regs);
-+
-+ if((syscall >= NR_syscalls) || (syscall < 1))
-+ res = -ENOSYS;
-+ else res = EXECUTE_SYSCALL(syscall, regs);
-+
-+ return(res);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/syscall_user.c um/arch/um/kernel/skas/syscall_user.c
---- orig/arch/um/kernel/skas/syscall_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/syscall_user.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,46 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdlib.h>
-+#include <signal.h>
-+#include "kern_util.h"
-+#include "syscall_user.h"
-+#include "sysdep/ptrace.h"
-+#include "sysdep/sigcontext.h"
-+
-+/* XXX Bogus */
-+#define ERESTARTSYS 512
-+#define ERESTARTNOINTR 513
-+#define ERESTARTNOHAND 514
-+
-+void handle_syscall(union uml_pt_regs *regs)
-+{
-+ long result;
-+ int index;
-+
-+ index = record_syscall_start(UPT_SYSCALL_NR(regs));
-+
-+ syscall_trace();
-+ result = execute_syscall(regs);
-+
-+ REGS_SET_SYSCALL_RETURN(regs->skas.regs, result);
-+ if((result == -ERESTARTNOHAND) || (result == -ERESTARTSYS) ||
-+ (result == -ERESTARTNOINTR))
-+ do_signal(result);
-+
-+ syscall_trace();
-+ record_syscall_end(index, result);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/sys-i386/Makefile um/arch/um/kernel/skas/sys-i386/Makefile
---- orig/arch/um/kernel/skas/sys-i386/Makefile 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/sys-i386/Makefile 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,17 @@
-+#
-+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+# Licensed under the GPL
-+#
-+
-+O_TARGET = sys-i386.o
-+
-+obj-y = sigcontext.o
-+
-+USER_OBJS = sigcontext.o
-+
-+include $(TOPDIR)/Rules.make
-+
-+$(USER_OBJS) : %.o: %.c
-+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $<
-+
-+clean :
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/sys-i386/sigcontext.c um/arch/um/kernel/skas/sys-i386/sigcontext.c
---- orig/arch/um/kernel/skas/sys-i386/sigcontext.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/sys-i386/sigcontext.c 2003-11-19 03:27:43.000000000 -0500
-@@ -0,0 +1,114 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <errno.h>
-+#include <asm/sigcontext.h>
-+#include <sys/ptrace.h>
-+#include <linux/ptrace.h>
-+#include "sysdep/ptrace.h"
-+#include "sysdep/ptrace_user.h"
-+#include "kern_util.h"
-+#include "user.h"
-+#include "sigcontext.h"
-+#include "mode.h"
-+
-+int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs, void *from_ptr)
-+{
-+ struct sigcontext sc, *from = from_ptr;
-+ unsigned long fpregs[FP_FRAME_SIZE];
-+ int err;
-+
-+ err = copy_from_user_proc(&sc, from, sizeof(sc));
-+ err |= copy_from_user_proc(fpregs, sc.fpstate, sizeof(fpregs));
-+ if(err)
-+ return(err);
-+
-+ regs->skas.regs[GS] = sc.gs;
-+ regs->skas.regs[FS] = sc.fs;
-+ regs->skas.regs[ES] = sc.es;
-+ regs->skas.regs[DS] = sc.ds;
-+ regs->skas.regs[EDI] = sc.edi;
-+ regs->skas.regs[ESI] = sc.esi;
-+ regs->skas.regs[EBP] = sc.ebp;
-+ regs->skas.regs[UESP] = sc.esp;
-+ regs->skas.regs[EBX] = sc.ebx;
-+ regs->skas.regs[EDX] = sc.edx;
-+ regs->skas.regs[ECX] = sc.ecx;
-+ regs->skas.regs[EAX] = sc.eax;
-+ regs->skas.regs[EIP] = sc.eip;
-+ regs->skas.regs[CS] = sc.cs;
-+ regs->skas.regs[EFL] = sc.eflags;
-+ regs->skas.regs[SS] = sc.ss;
-+ regs->skas.fault_addr = sc.cr2;
-+ regs->skas.fault_type = FAULT_WRITE(sc.err);
-+ regs->skas.trap_type = sc.trapno;
-+
-+ err = ptrace(PTRACE_SETFPREGS, pid, 0, fpregs);
-+ if(err < 0){
-+ printk("copy_sc_to_user - PTRACE_SETFPREGS failed, "
-+ "errno = %d\n", errno);
-+ return(1);
-+ }
-+
-+ return(0);
-+}
-+
-+int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp,
-+ union uml_pt_regs *regs, unsigned long fault_addr,
-+ int fault_type)
-+{
-+ struct sigcontext sc, *to = to_ptr;
-+ struct _fpstate *to_fp;
-+ unsigned long fpregs[FP_FRAME_SIZE];
-+ int err;
-+
-+ sc.gs = regs->skas.regs[GS];
-+ sc.fs = regs->skas.regs[FS];
-+ sc.es = regs->skas.regs[ES];
-+ sc.ds = regs->skas.regs[DS];
-+ sc.edi = regs->skas.regs[EDI];
-+ sc.esi = regs->skas.regs[ESI];
-+ sc.ebp = regs->skas.regs[EBP];
-+ sc.esp = regs->skas.regs[UESP];
-+ sc.ebx = regs->skas.regs[EBX];
-+ sc.edx = regs->skas.regs[EDX];
-+ sc.ecx = regs->skas.regs[ECX];
-+ sc.eax = regs->skas.regs[EAX];
-+ sc.eip = regs->skas.regs[EIP];
-+ sc.cs = regs->skas.regs[CS];
-+ sc.eflags = regs->skas.regs[EFL];
-+ sc.esp_at_signal = regs->skas.regs[UESP];
-+ sc.ss = regs->skas.regs[SS];
-+ sc.cr2 = fault_addr;
-+ sc.err = TO_SC_ERR(fault_type);
-+ sc.trapno = regs->skas.trap_type;
-+
-+ err = ptrace(PTRACE_GETFPREGS, pid, 0, fpregs);
-+ if(err < 0){
-+ printk("copy_sc_to_user - PTRACE_GETFPREGS failed, "
-+ "errno = %d\n", errno);
-+ return(1);
-+ }
-+ to_fp = (struct _fpstate *)
-+ (fp ? (unsigned long) fp : ((unsigned long) to + sizeof(*to)));
-+ sc.fpstate = to_fp;
-+
-+ if(err)
-+ return(err);
-+
-+ return(copy_to_user_proc(to, &sc, sizeof(sc)) ||
-+ copy_to_user_proc(to_fp, fpregs, sizeof(fpregs)));
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/time.c um/arch/um/kernel/skas/time.c
---- orig/arch/um/kernel/skas/time.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/time.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,30 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <sys/signal.h>
-+#include <sys/time.h>
-+#include "time_user.h"
-+#include "process.h"
-+#include "user.h"
-+
-+void user_time_init_skas(void)
-+{
-+ if(signal(SIGALRM, (__sighandler_t) alarm_handler) == SIG_ERR)
-+ panic("Couldn't set SIGALRM handler");
-+ if(signal(SIGVTALRM, (__sighandler_t) alarm_handler) == SIG_ERR)
-+ panic("Couldn't set SIGVTALRM handler");
-+ set_interval(ITIMER_VIRTUAL);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/tlb.c um/arch/um/kernel/skas/tlb.c
---- orig/arch/um/kernel/skas/tlb.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/tlb.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,153 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/stddef.h"
-+#include "linux/sched.h"
-+#include "asm/page.h"
-+#include "asm/pgtable.h"
-+#include "asm/mmu.h"
-+#include "user_util.h"
-+#include "mem_user.h"
-+#include "skas.h"
-+#include "os.h"
-+
-+static void fix_range(struct mm_struct *mm, unsigned long start_addr,
-+ unsigned long end_addr, int force)
-+{
-+ pgd_t *npgd;
-+ pmd_t *npmd;
-+ pte_t *npte;
-+ unsigned long addr;
-+ int r, w, x, err, fd;
-+
-+ if(mm == NULL) return;
-+ fd = mm->context.skas.mm_fd;
-+ for(addr = start_addr; addr < end_addr;){
-+ npgd = pgd_offset(mm, addr);
-+ npmd = pmd_offset(npgd, addr);
-+ if(pmd_present(*npmd)){
-+ npte = pte_offset(npmd, addr);
-+ r = pte_read(*npte);
-+ w = pte_write(*npte);
-+ x = pte_exec(*npte);
-+ if(!pte_dirty(*npte)) w = 0;
-+ if(!pte_young(*npte)){
-+ r = 0;
-+ w = 0;
-+ }
-+ if(force || pte_newpage(*npte)){
-+ err = unmap(fd, (void *) addr, PAGE_SIZE);
-+ if(err < 0)
-+ panic("munmap failed, errno = %d\n",
-+ -err);
-+ if(pte_present(*npte))
-+ map(fd, addr,
-+ pte_val(*npte) & PAGE_MASK,
-+ PAGE_SIZE, r, w, x);
-+ }
-+ else if(pte_newprot(*npte)){
-+ protect(fd, addr, PAGE_SIZE, r, w, x, 1);
-+ }
-+ *npte = pte_mkuptodate(*npte);
-+ addr += PAGE_SIZE;
-+ }
-+ else {
-+ if(force || pmd_newpage(*npmd)){
-+ err = unmap(fd, (void *) addr, PMD_SIZE);
-+ if(err < 0)
-+ panic("munmap failed, errno = %d\n",
-+ -err);
-+ pmd_mkuptodate(*npmd);
-+ }
-+ addr += PMD_SIZE;
-+ }
-+ }
-+}
-+
-+static void flush_kernel_vm_range(unsigned long start, unsigned long end)
-+{
-+ struct mm_struct *mm;
-+ pgd_t *pgd;
-+ pmd_t *pmd;
-+ pte_t *pte;
-+ unsigned long addr;
-+ int updated = 0, err;
-+
-+ mm = &init_mm;
-+ for(addr = start_vm; addr < end_vm;){
-+ pgd = pgd_offset(mm, addr);
-+ pmd = pmd_offset(pgd, addr);
-+ if(pmd_present(*pmd)){
-+ pte = pte_offset(pmd, addr);
-+ if(!pte_present(*pte) || pte_newpage(*pte)){
-+ updated = 1;
-+ err = os_unmap_memory((void *) addr,
-+ PAGE_SIZE);
-+ if(err < 0)
-+ panic("munmap failed, errno = %d\n",
-+ -err);
-+ if(pte_present(*pte))
-+ map_memory(addr,
-+ pte_val(*pte) & PAGE_MASK,
-+ PAGE_SIZE, 1, 1, 1);
-+ }
-+ else if(pte_newprot(*pte)){
-+ updated = 1;
-+ protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1);
-+ }
-+ addr += PAGE_SIZE;
-+ }
-+ else {
-+ if(pmd_newpage(*pmd)){
-+ updated = 1;
-+ err = os_unmap_memory((void *) addr, PMD_SIZE);
-+ if(err < 0)
-+ panic("munmap failed, errno = %d\n",
-+ -err);
-+ }
-+ addr += PMD_SIZE;
-+ }
-+ }
-+}
-+
-+void flush_tlb_kernel_vm_skas(void)
-+{
-+ flush_kernel_vm_range(start_vm, end_vm);
-+}
-+
-+void __flush_tlb_one_skas(unsigned long addr)
-+{
-+ flush_kernel_vm_range(addr, addr + PAGE_SIZE);
-+}
-+
-+void flush_tlb_range_skas(struct mm_struct *mm, unsigned long start,
-+ unsigned long end)
-+{
-+ if(mm == NULL)
-+ flush_kernel_vm_range(start, end);
-+ else fix_range(mm, start, end, 0);
-+}
-+
-+void flush_tlb_mm_skas(struct mm_struct *mm)
-+{
-+ flush_tlb_kernel_vm_skas();
-+ fix_range(mm, 0, host_task_size, 0);
-+}
-+
-+void force_flush_all_skas(void)
-+{
-+ fix_range(current->mm, 0, host_task_size, 1);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/trap_user.c um/arch/um/kernel/skas/trap_user.c
---- orig/arch/um/kernel/skas/trap_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/trap_user.c 2004-01-21 01:17:05.000000000 -0500
-@@ -0,0 +1,66 @@
-+/*
-+ * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <signal.h>
-+#include <errno.h>
-+#include <asm/sigcontext.h>
-+#include "sysdep/ptrace.h"
-+#include "signal_user.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "task.h"
-+#include "sigcontext.h"
-+
-+void sig_handler_common_skas(int sig, void *sc_ptr)
-+{
-+ struct sigcontext *sc = sc_ptr;
-+ struct skas_regs *r;
-+ struct signal_info *info;
-+ int save_errno = errno;
-+ int save_user;
-+
-+ r = &TASK_REGS(get_current())->skas;
-+ save_user = r->is_user;
-+ r->is_user = 0;
-+ r->fault_addr = SC_FAULT_ADDR(sc);
-+ r->fault_type = SC_FAULT_TYPE(sc);
-+ r->trap_type = SC_TRAP_TYPE(sc);
-+
-+ change_sig(SIGUSR1, 1);
-+ info = &sig_info[sig];
-+ if(!info->is_irq) unblock_signals();
-+
-+ (*info->handler)(sig, (union uml_pt_regs *) r);
-+
-+ errno = save_errno;
-+ r->is_user = save_user;
-+}
-+
-+extern int missed_ticks[];
-+
-+void user_signal(int sig, union uml_pt_regs *regs)
-+{
-+ struct signal_info *info;
-+
-+ regs->skas.is_user = 1;
-+ regs->skas.fault_addr = 0;
-+ regs->skas.fault_type = 0;
-+ regs->skas.trap_type = 0;
-+ info = &sig_info[sig];
-+ (*info->handler)(sig, regs);
-+
-+ unblock_signals();
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/uaccess.c um/arch/um/kernel/skas/uaccess.c
---- orig/arch/um/kernel/skas/uaccess.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/uaccess.c 2003-12-22 01:30:09.000000000 -0500
-@@ -0,0 +1,217 @@
-+/*
-+ * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/stddef.h"
-+#include "linux/kernel.h"
-+#include "linux/string.h"
-+#include "linux/fs.h"
-+#include "linux/highmem.h"
-+#include "asm/page.h"
-+#include "asm/pgtable.h"
-+#include "asm/uaccess.h"
-+#include "kern_util.h"
-+
-+extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
-+ pte_t *pte_out);
-+
-+static unsigned long maybe_map(unsigned long virt, int is_write)
-+{
-+ pte_t pte;
-+
-+ void *phys = um_virt_to_phys(current, virt, &pte);
-+ int dummy_code;
-+
-+ if(IS_ERR(phys) || (is_write && !pte_write(pte))){
-+ if(!handle_page_fault(virt, 0, is_write, 0, &dummy_code))
-+ return(0);
-+ phys = um_virt_to_phys(current, virt, NULL);
-+ }
-+ return((unsigned long) phys);
-+}
-+
-+static int do_op(unsigned long addr, int len, int is_write,
-+ int (*op)(unsigned long addr, int len, void *arg), void *arg)
-+{
-+ struct page *page;
-+ int n;
-+
-+ addr = maybe_map(addr, is_write);
-+ if(addr == -1)
-+ return(-1);
-+
-+ page = phys_to_page(addr);
-+ addr = (unsigned long) kmap(page) + (addr & ~PAGE_MASK);
-+ n = (*op)(addr, len, arg);
-+ kunmap(page);
-+
-+ return(n);
-+}
-+
-+static int buffer_op(unsigned long addr, int len, int is_write,
-+ int (*op)(unsigned long addr, int len, void *arg),
-+ void *arg)
-+{
-+ int size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len);
-+ int remain = len, n;
-+
-+ n = do_op(addr, size, is_write, op, arg);
-+ if(n != 0)
-+ return(n < 0 ? remain : 0);
-+
-+ addr += size;
-+ remain -= size;
-+ if(remain == 0)
-+ return(0);
-+
-+ while(addr < ((addr + remain) & PAGE_MASK)){
-+ n = do_op(addr, PAGE_SIZE, is_write, op, arg);
-+ if(n != 0)
-+ return(n < 0 ? remain : 0);
-+
-+ addr += PAGE_SIZE;
-+ remain -= PAGE_SIZE;
-+ }
-+ if(remain == 0)
-+ return(0);
-+
-+ n = do_op(addr, remain, is_write, op, arg);
-+ if(n != 0)
-+ return(n < 0 ? remain : 0);
-+ return(0);
-+}
-+
-+static int copy_chunk_from_user(unsigned long from, int len, void *arg)
-+{
-+ unsigned long *to_ptr = arg, to = *to_ptr;
-+
-+ memcpy((void *) to, (void *) from, len);
-+ *to_ptr += len;
-+ return(0);
-+}
-+
-+int copy_from_user_skas(void *to, const void *from, int n)
-+{
-+ if(segment_eq(get_fs(), KERNEL_DS)){
-+ memcpy(to, from, n);
-+ return(0);
-+ }
-+
-+ return(access_ok_skas(VERIFY_READ, from, n) ?
-+ buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to):
-+ n);
-+}
-+
-+static int copy_chunk_to_user(unsigned long to, int len, void *arg)
-+{
-+ unsigned long *from_ptr = arg, from = *from_ptr;
-+
-+ memcpy((void *) to, (void *) from, len);
-+ *from_ptr += len;
-+ return(0);
-+}
-+
-+int copy_to_user_skas(void *to, const void *from, int n)
-+{
-+ if(segment_eq(get_fs(), KERNEL_DS)){
-+ memcpy(to, from, n);
-+ return(0);
-+ }
-+
-+ return(access_ok_skas(VERIFY_WRITE, to, n) ?
-+ buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) :
-+ n);
-+}
-+
-+static int strncpy_chunk_from_user(unsigned long from, int len, void *arg)
-+{
-+ char **to_ptr = arg, *to = *to_ptr;
-+ int n;
-+
-+ strncpy(to, (void *) from, len);
-+ n = strnlen(to, len);
-+ *to_ptr += n;
-+
-+ if(n < len)
-+ return(1);
-+ return(0);
-+}
-+
-+int strncpy_from_user_skas(char *dst, const char *src, int count)
-+{
-+ int n;
-+ char *ptr = dst;
-+
-+ if(segment_eq(get_fs(), KERNEL_DS)){
-+ strncpy(dst, src, count);
-+ return(strnlen(dst, count));
-+ }
-+
-+ if(!access_ok_skas(VERIFY_READ, src, 1))
-+ return(-EFAULT);
-+
-+ n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user,
-+ &ptr);
-+ if(n != 0)
-+ return(-EFAULT);
-+ return(strnlen(dst, count));
-+}
-+
-+static int clear_chunk(unsigned long addr, int len, void *unused)
-+{
-+ memset((void *) addr, 0, len);
-+ return(0);
-+}
-+
-+int __clear_user_skas(void *mem, int len)
-+{
-+ return(buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL));
-+}
-+
-+int clear_user_skas(void *mem, int len)
-+{
-+ if(segment_eq(get_fs(), KERNEL_DS)){
-+ memset(mem, 0, len);
-+ return(0);
-+ }
-+
-+ return(access_ok_skas(VERIFY_WRITE, mem, len) ?
-+ buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len);
-+}
-+
-+static int strnlen_chunk(unsigned long str, int len, void *arg)
-+{
-+ int *len_ptr = arg, n;
-+
-+ n = strnlen((void *) str, len);
-+ *len_ptr += n;
-+
-+ if(n < len)
-+ return(1);
-+ return(0);
-+}
-+
-+int strnlen_user_skas(const void *str, int len)
-+{
-+ int count = 0, n;
-+
-+ if(segment_eq(get_fs(), KERNEL_DS))
-+ return(strnlen(str, len) + 1);
-+
-+ n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count);
-+ if(n == 0)
-+ return(count + 1);
-+ return(-EFAULT);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/util/Makefile um/arch/um/kernel/skas/util/Makefile
---- orig/arch/um/kernel/skas/util/Makefile 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/util/Makefile 2003-11-08 02:52:22.000000000 -0500
-@@ -0,0 +1,10 @@
-+all: mk_ptregs
-+
-+mk_ptregs : mk_ptregs.o
-+ $(HOSTCC) -o mk_ptregs mk_ptregs.o
-+
-+mk_ptregs.o : mk_ptregs.c
-+ $(HOSTCC) -c $<
-+
-+clean :
-+ $(RM) -f mk_ptregs *.o *~
-diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/util/mk_ptregs.c um/arch/um/kernel/skas/util/mk_ptregs.c
---- orig/arch/um/kernel/skas/util/mk_ptregs.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/skas/util/mk_ptregs.c 2003-12-22 01:31:11.000000000 -0500
-@@ -0,0 +1,51 @@
-+#include <stdio.h>
-+#include <asm/ptrace.h>
-+#include <asm/user.h>
-+
-+#define PRINT_REG(name, val) printf("#define HOST_%s %d\n", (name), (val))
-+
-+int main(int argc, char **argv)
-+{
-+ printf("/* Automatically generated by "
-+ "arch/um/kernel/skas/util/mk_ptregs */\n");
-+ printf("\n");
-+ printf("#ifndef __SKAS_PT_REGS_\n");
-+ printf("#define __SKAS_PT_REGS_\n");
-+ printf("\n");
-+ printf("#define HOST_FRAME_SIZE %d\n", FRAME_SIZE);
-+ printf("#define HOST_FP_SIZE %d\n",
-+ sizeof(struct user_i387_struct) / sizeof(unsigned long));
-+ printf("#define HOST_XFP_SIZE %d\n",
-+ sizeof(struct user_fxsr_struct) / sizeof(unsigned long));
-+
-+ PRINT_REG("IP", EIP);
-+ PRINT_REG("SP", UESP);
-+ PRINT_REG("EFLAGS", EFL);
-+ PRINT_REG("EAX", EAX);
-+ PRINT_REG("EBX", EBX);
-+ PRINT_REG("ECX", ECX);
-+ PRINT_REG("EDX", EDX);
-+ PRINT_REG("ESI", ESI);
-+ PRINT_REG("EDI", EDI);
-+ PRINT_REG("EBP", EBP);
-+ PRINT_REG("CS", CS);
-+ PRINT_REG("SS", SS);
-+ PRINT_REG("DS", DS);
-+ PRINT_REG("FS", FS);
-+ PRINT_REG("ES", ES);
-+ PRINT_REG("GS", GS);
-+ printf("\n");
-+ printf("#endif\n");
-+ return(0);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/smp.c um/arch/um/kernel/smp.c
---- orig/arch/um/kernel/smp.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/smp.c 2003-11-15 02:59:25.000000000 -0500
-@@ -0,0 +1,328 @@
-+/*
-+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/config.h"
-+
-+#ifdef CONFIG_SMP
-+
-+#include "linux/sched.h"
-+#include "linux/threads.h"
-+#include "linux/interrupt.h"
-+#include "asm/smp.h"
-+#include "asm/processor.h"
-+#include "asm/spinlock.h"
-+#include "asm/softirq.h"
-+#include "asm/hardirq.h"
-+#include "asm/tlb.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "irq_user.h"
-+#include "kern.h"
-+#include "os.h"
-+
-+/* Total count of live CPUs, set by smp_boot_cpus */
-+int smp_num_cpus = 1;
-+
-+/* The 'big kernel lock' */
-+spinlock_cacheline_t kernel_flag_cacheline = {SPIN_LOCK_UNLOCKED};
-+
-+/* Per CPU bogomips and other parameters */
-+
-+/* The only piece used here is the ipi pipe, which is set before SMP is
-+ * started and never changed.
-+ */
-+struct cpuinfo_um cpu_data[NR_CPUS];
-+
-+/* CPU online map, set by smp_boot_cpus */
-+unsigned long cpu_online_map;
-+
-+atomic_t global_bh_count;
-+
-+/* Set when the idlers are all forked */
-+int smp_threads_ready = 0;
-+
-+/* Not used by UML */
-+unsigned char global_irq_holder = 0;
-+unsigned volatile long global_irq_lock;
-+
-+/* A statistic, can be a little off */
-+static int num_reschedules_sent = 0;
-+
-+mmu_gather_t mmu_gathers[NR_CPUS];
-+
-+void smp_send_reschedule(int cpu)
-+{
-+ os_write_file(cpu_data[cpu].ipi_pipe[1], "R", 1);
-+ num_reschedules_sent++;
-+}
-+
-+static void show(char * str)
-+{
-+ int cpu = smp_processor_id();
-+
-+ printk(KERN_INFO "\n%s, CPU %d:\n", str, cpu);
-+}
-+
-+#define MAXCOUNT 100000000
-+
-+static inline void wait_on_bh(void)
-+{
-+ int count = MAXCOUNT;
-+ do {
-+ if (!--count) {
-+ show("wait_on_bh");
-+ count = ~0;
-+ }
-+ /* nothing .. wait for the other bh's to go away */
-+ } while (atomic_read(&global_bh_count) != 0);
-+}
-+
-+/*
-+ * This is called when we want to synchronize with
-+ * bottom half handlers. We need to wait until
-+ * no other CPU is executing any bottom half handler.
-+ *
-+ * Don't wait if we're already running in an interrupt
-+ * context or are inside a bh handler.
-+ */
-+void synchronize_bh(void)
-+{
-+ if (atomic_read(&global_bh_count) && !in_interrupt())
-+ wait_on_bh();
-+}
-+
-+void smp_send_stop(void)
-+{
-+ int i;
-+
-+ printk(KERN_INFO "Stopping all CPUs...");
-+ for(i = 0; i < ncpus; i++){
-+ if(i == current->processor)
-+ continue;
-+ os_write_file(cpu_data[i].ipi_pipe[1], "S", 1);
-+ }
-+ printk("done\n");
-+}
-+
-+
-+static atomic_t smp_commenced = ATOMIC_INIT(0);
-+static volatile unsigned long smp_callin_map = 0;
-+
-+void smp_commence(void)
-+{
-+ printk("All CPUs are go!\n");
-+
-+ wmb();
-+ atomic_set(&smp_commenced, 1);
-+}
-+
-+static int idle_proc(void *unused)
-+{
-+ int cpu, err;
-+
-+ set_current(current);
-+ del_from_runqueue(current);
-+ unhash_process(current);
-+
-+ cpu = current->processor;
-+ err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1);
-+ if(err < 0)
-+ panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err);
-+
-+ activate_ipi(cpu_data[cpu].ipi_pipe[0],
-+ current->thread.mode.tt.extern_pid);
-+
-+ wmb();
-+ if (test_and_set_bit(current->processor, &smp_callin_map)) {
-+ printk("huh, CPU#%d already present??\n", current->processor);
-+ BUG();
-+ }
-+
-+ while (!atomic_read(&smp_commenced))
-+ cpu_relax();
-+
-+ init_idle();
-+ cpu_idle();
-+ return(0);
-+}
-+
-+static int idle_thread(int (*fn)(void *), int cpu)
-+{
-+ struct task_struct *new_task;
-+ int pid;
-+ unsigned char c;
-+
-+ current->thread.request.u.thread.proc = fn;
-+ current->thread.request.u.thread.arg = NULL;
-+ pid = do_fork(CLONE_VM | CLONE_PID, 0, NULL, 0);
-+ if(pid < 0)
-+ panic("do_fork failed in idle_thread");
-+ new_task = get_task(pid, 1);
-+
-+ cpu_tasks[cpu] = ((struct cpu_task)
-+ { .pid = new_task->thread.mode.tt.extern_pid,
-+ .task = new_task } );
-+ init_tasks[cpu] = new_task;
-+ new_task->processor = cpu;
-+ new_task->cpus_allowed = 1 << cpu;
-+ new_task->cpus_runnable = new_task->cpus_allowed;
-+ CHOOSE_MODE(os_write_file(new_task->thread.mode.tt.switch_pipe[1], &c,
-+ sizeof(c)),
-+ ({ panic("skas mode doesn't support SMP"); }));
-+ return(new_task->thread.mode.tt.extern_pid);
-+}
-+
-+void smp_boot_cpus(void)
-+{
-+ int err;
-+
-+ set_bit(0, &cpu_online_map);
-+ set_bit(0, &smp_callin_map);
-+
-+ err = os_pipe(cpu_data[0].ipi_pipe, 1, 1);
-+ if(err < 0)
-+ panic("CPU#0 failed to create IPI pipe, err = %d", -err);
-+
-+ activate_ipi(cpu_data[0].ipi_pipe[0],
-+ current->thread.mode.tt.extern_pid);
-+
-+ if(ncpus < 1){
-+ printk(KERN_INFO "ncpus set to 1\n");
-+ ncpus = 1;
-+ }
-+ else if(ncpus > NR_CPUS){
-+ printk(KERN_INFO
-+ "ncpus can't be greater than NR_CPUS, set to %d\n",
-+ NR_CPUS);
-+ ncpus = NR_CPUS;
-+ }
-+
-+ if(ncpus > 1){
-+ int i, pid;
-+
-+ printk(KERN_INFO "Starting up other processors:\n");
-+ for(i=1;i<ncpus;i++){
-+ int waittime;
-+
-+ /* Do this early, for hard_smp_processor_id() */
-+ cpu_tasks[i].pid = -1;
-+ set_bit(i, &cpu_online_map);
-+ smp_num_cpus++;
-+
-+ pid = idle_thread(idle_proc, i);
-+ printk(KERN_INFO "\t#%d - idle thread pid = %d.. ",
-+ i, pid);
-+
-+ waittime = 200000000;
-+ while (waittime-- && !test_bit(i, &smp_callin_map))
-+ cpu_relax();
-+
-+ if (test_bit(i, &smp_callin_map))
-+ printk("online\n");
-+ else {
-+ printk("failed\n");
-+ clear_bit(i, &cpu_online_map);
-+ }
-+ }
-+ }
-+}
-+
-+int setup_profiling_timer(unsigned int multiplier)
-+{
-+ printk(KERN_INFO "setup_profiling_timer\n");
-+ return(0);
-+}
-+
-+void smp_call_function_slave(int cpu);
-+
-+void IPI_handler(int cpu)
-+{
-+ unsigned char c;
-+ int fd;
-+
-+ fd = cpu_data[cpu].ipi_pipe[0];
-+ while (os_read_file(fd, &c, 1) == 1) {
-+ switch (c) {
-+ case 'C':
-+ smp_call_function_slave(cpu);
-+ break;
-+
-+ case 'R':
-+ current->need_resched = 1;
-+ break;
-+
-+ case 'S':
-+ printk("CPU#%d stopping\n", cpu);
-+ while(1)
-+ pause();
-+ break;
-+
-+ default:
-+ printk("CPU#%d received unknown IPI [%c]!\n", cpu, c);
-+ break;
-+ }
-+ }
-+}
-+
-+int hard_smp_processor_id(void)
-+{
-+ return(pid_to_processor_id(os_getpid()));
-+}
-+
-+static spinlock_t call_lock = SPIN_LOCK_UNLOCKED;
-+static atomic_t scf_started;
-+static atomic_t scf_finished;
-+static void (*func)(void *info);
-+static void *info;
-+
-+void smp_call_function_slave(int cpu)
-+{
-+ atomic_inc(&scf_started);
-+ (*func)(info);
-+ atomic_inc(&scf_finished);
-+}
-+
-+int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic,
-+ int wait)
-+{
-+ int cpus = smp_num_cpus - 1;
-+ int i;
-+
-+ if (!cpus)
-+ return 0;
-+
-+ spin_lock_bh(&call_lock);
-+ atomic_set(&scf_started, 0);
-+ atomic_set(&scf_finished, 0);
-+ func = _func;
-+ info = _info;
-+
-+ for (i=0;i<NR_CPUS;i++)
-+ if (i != current->processor && test_bit(i, &cpu_online_map))
-+ os_write_file(cpu_data[i].ipi_pipe[1], "C", 1);
-+
-+ while (atomic_read(&scf_started) != cpus)
-+ barrier();
-+
-+ if (wait)
-+ while (atomic_read(&scf_finished) != cpus)
-+ barrier();
-+
-+ spin_unlock_bh(&call_lock);
-+ return 0;
-+}
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/syscall_kern.c um/arch/um/kernel/syscall_kern.c
---- orig/arch/um/kernel/syscall_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/syscall_kern.c 2004-01-10 06:37:46.000000000 -0500
-@@ -0,0 +1,343 @@
-+/*
-+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/sched.h"
-+#include "linux/file.h"
-+#include "linux/smp_lock.h"
-+#include "linux/mm.h"
-+#include "linux/utsname.h"
-+#include "linux/msg.h"
-+#include "linux/shm.h"
-+#include "linux/sys.h"
-+#include "linux/unistd.h"
-+#include "linux/slab.h"
-+#include "linux/utime.h"
-+#include "asm/mman.h"
-+#include "asm/uaccess.h"
-+#include "asm/ipc.h"
-+#include "kern_util.h"
-+#include "user_util.h"
-+#include "sysdep/syscalls.h"
-+#include "mode_kern.h"
-+#include "choose-mode.h"
-+
-+/* Unlocked, I don't care if this is a bit off */
-+int nsyscalls = 0;
-+
-+long um_mount(char * dev_name, char * dir_name, char * type,
-+ unsigned long new_flags, void * data)
-+{
-+ if(type == NULL) type = "";
-+ return(sys_mount(dev_name, dir_name, type, new_flags, data));
-+}
-+
-+long sys_fork(void)
-+{
-+ long ret;
-+
-+ current->thread.forking = 1;
-+ ret = do_fork(SIGCHLD, 0, NULL, 0);
-+ current->thread.forking = 0;
-+ return(ret);
-+}
-+
-+long sys_clone(unsigned long clone_flags, unsigned long newsp)
-+{
-+ long ret;
-+
-+ current->thread.forking = 1;
-+ ret = do_fork(clone_flags, newsp, NULL, 0);
-+ current->thread.forking = 0;
-+ return(ret);
-+}
-+
-+long sys_vfork(void)
-+{
-+ long ret;
-+
-+ current->thread.forking = 1;
-+ ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0);
-+ current->thread.forking = 0;
-+ return(ret);
-+}
-+
-+/* common code for old and new mmaps */
-+long do_mmap2(struct mm_struct *mm, unsigned long addr, unsigned long len,
-+ unsigned long prot, unsigned long flags, unsigned long fd,
-+ unsigned long pgoff)
-+{
-+ int error = -EBADF;
-+ struct file * file = NULL;
-+
-+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-+ if (!(flags & MAP_ANONYMOUS)) {
-+ file = fget(fd);
-+ if (!file)
-+ goto out;
-+ }
-+
-+ down_write(&mm->mmap_sem);
-+ error = do_mmap_pgoff(mm, file, addr, len, prot, flags, pgoff);
-+ up_write(&mm->mmap_sem);
-+
-+ if (file)
-+ fput(file);
-+ out:
-+ return error;
-+}
-+
-+long sys_mmap2(unsigned long addr, unsigned long len,
-+ unsigned long prot, unsigned long flags,
-+ unsigned long fd, unsigned long pgoff)
-+{
-+ return do_mmap2(current->mm, addr, len, prot, flags, fd, pgoff);
-+}
-+
-+/*
-+ * Perform the select(nd, in, out, ex, tv) and mmap() system
-+ * calls. Linux/i386 didn't use to be able to handle more than
-+ * 4 system call parameters, so these system calls used a memory
-+ * block for parameter passing..
-+ */
-+
-+struct mmap_arg_struct {
-+ unsigned long addr;
-+ unsigned long len;
-+ unsigned long prot;
-+ unsigned long flags;
-+ unsigned long fd;
-+ unsigned long offset;
-+};
-+
-+int old_mmap(unsigned long addr, unsigned long len,
-+ unsigned long prot, unsigned long flags,
-+ unsigned long fd, unsigned long offset)
-+{
-+ int err = -EINVAL;
-+ if (offset & ~PAGE_MASK)
-+ goto out;
-+
-+ err = do_mmap2(current->mm, addr, len, prot, flags, fd,
-+ offset >> PAGE_SHIFT);
-+ out:
-+ return err;
-+}
-+/*
-+ * sys_pipe() is the normal C calling standard for creating
-+ * a pipe. It's not the way unix traditionally does this, though.
-+ */
-+int sys_pipe(unsigned long * fildes)
-+{
-+ int fd[2];
-+ int error;
-+
-+ error = do_pipe(fd);
-+ if (!error) {
-+ if (copy_to_user(fildes, fd, sizeof(fd)))
-+ error = -EFAULT;
-+ }
-+ return error;
-+}
-+
-+int sys_pause(void)
-+{
-+ current->state = TASK_INTERRUPTIBLE;
-+ schedule();
-+ return -ERESTARTNOHAND;
-+}
-+
-+int sys_sigaction(int sig, const struct old_sigaction *act,
-+ struct old_sigaction *oact)
-+{
-+ struct k_sigaction new_ka, old_ka;
-+ int ret;
-+
-+ if (act) {
-+ old_sigset_t mask;
-+ if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
-+ __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
-+ __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
-+ return -EFAULT;
-+ __get_user(new_ka.sa.sa_flags, &act->sa_flags);
-+ __get_user(mask, &act->sa_mask);
-+ siginitset(&new_ka.sa.sa_mask, mask);
-+ }
-+
-+ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
-+
-+ if (!ret && oact) {
-+ if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
-+ __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
-+ __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
-+ return -EFAULT;
-+ __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
-+ __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
-+ }
-+
-+ return ret;
-+}
-+
-+/*
-+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
-+ *
-+ * This is really horribly ugly.
-+ */
-+int sys_ipc (uint call, int first, int second,
-+ int third, void *ptr, long fifth)
-+{
-+ int version, ret;
-+
-+ version = call >> 16; /* hack for backward compatibility */
-+ call &= 0xffff;
-+
-+ switch (call) {
-+ case SEMOP:
-+ return sys_semop (first, (struct sembuf *)ptr, second);
-+ case SEMGET:
-+ return sys_semget (first, second, third);
-+ case SEMCTL: {
-+ union semun fourth;
-+ if (!ptr)
-+ return -EINVAL;
-+ if (get_user(fourth.__pad, (void **) ptr))
-+ return -EFAULT;
-+ return sys_semctl (first, second, third, fourth);
-+ }
-+
-+ case MSGSND:
-+ return sys_msgsnd (first, (struct msgbuf *) ptr,
-+ second, third);
-+ case MSGRCV:
-+ switch (version) {
-+ case 0: {
-+ struct ipc_kludge tmp;
-+ if (!ptr)
-+ return -EINVAL;
-+
-+ if (copy_from_user(&tmp,
-+ (struct ipc_kludge *) ptr,
-+ sizeof (tmp)))
-+ return -EFAULT;
-+ return sys_msgrcv (first, tmp.msgp, second,
-+ tmp.msgtyp, third);
-+ }
-+ default:
-+ panic("msgrcv with version != 0");
-+ return sys_msgrcv (first,
-+ (struct msgbuf *) ptr,
-+ second, fifth, third);
-+ }
-+ case MSGGET:
-+ return sys_msgget ((key_t) first, second);
-+ case MSGCTL:
-+ return sys_msgctl (first, second, (struct msqid_ds *) ptr);
-+
-+ case SHMAT:
-+ switch (version) {
-+ default: {
-+ ulong raddr;
-+ ret = sys_shmat (first, (char *) ptr, second, &raddr);
-+ if (ret)
-+ return ret;
-+ return put_user (raddr, (ulong *) third);
-+ }
-+ case 1: /* iBCS2 emulator entry point */
-+ if (!segment_eq(get_fs(), get_ds()))
-+ return -EINVAL;
-+ return sys_shmat (first, (char *) ptr, second, (ulong *) third);
-+ }
-+ case SHMDT:
-+ return sys_shmdt ((char *)ptr);
-+ case SHMGET:
-+ return sys_shmget (first, second, third);
-+ case SHMCTL:
-+ return sys_shmctl (first, second,
-+ (struct shmid_ds *) ptr);
-+ default:
-+ return -EINVAL;
-+ }
-+}
-+
-+int sys_uname(struct old_utsname * name)
-+{
-+ int err;
-+ if (!name)
-+ return -EFAULT;
-+ down_read(&uts_sem);
-+ err=copy_to_user(name, &system_utsname, sizeof (*name));
-+ up_read(&uts_sem);
-+ return err?-EFAULT:0;
-+}
-+
-+int sys_olduname(struct oldold_utsname * name)
-+{
-+ int error;
-+
-+ if (!name)
-+ return -EFAULT;
-+ if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
-+ return -EFAULT;
-+
-+ down_read(&uts_sem);
-+
-+ error = __copy_to_user(&name->sysname,&system_utsname.sysname,
-+ __OLD_UTS_LEN);
-+ error |= __put_user(0,name->sysname+__OLD_UTS_LEN);
-+ error |= __copy_to_user(&name->nodename,&system_utsname.nodename,
-+ __OLD_UTS_LEN);
-+ error |= __put_user(0,name->nodename+__OLD_UTS_LEN);
-+ error |= __copy_to_user(&name->release,&system_utsname.release,
-+ __OLD_UTS_LEN);
-+ error |= __put_user(0,name->release+__OLD_UTS_LEN);
-+ error |= __copy_to_user(&name->version,&system_utsname.version,
-+ __OLD_UTS_LEN);
-+ error |= __put_user(0,name->version+__OLD_UTS_LEN);
-+ error |= __copy_to_user(&name->machine,&system_utsname.machine,
-+ __OLD_UTS_LEN);
-+ error |= __put_user(0,name->machine+__OLD_UTS_LEN);
-+
-+ up_read(&uts_sem);
-+
-+ error = error ? -EFAULT : 0;
-+
-+ return error;
-+}
-+
-+int sys_sigaltstack(const stack_t *uss, stack_t *uoss)
-+{
-+ return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs)));
-+}
-+
-+long execute_syscall(void *r)
-+{
-+ return(CHOOSE_MODE_PROC(execute_syscall_tt, execute_syscall_skas, r));
-+}
-+
-+spinlock_t syscall_lock = SPIN_LOCK_UNLOCKED;
-+
-+static int syscall_index = 0;
-+
-+int next_syscall_index(int limit)
-+{
-+ int ret;
-+
-+ spin_lock(&syscall_lock);
-+ ret = syscall_index;
-+ if(++syscall_index == limit)
-+ syscall_index = 0;
-+ spin_unlock(&syscall_lock);
-+ return(ret);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/sys_call_table.c um/arch/um/kernel/sys_call_table.c
---- orig/arch/um/kernel/sys_call_table.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/sys_call_table.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,496 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/unistd.h"
-+#include "linux/version.h"
-+#include "linux/sys.h"
-+#include "asm/signal.h"
-+#include "sysdep/syscalls.h"
-+#include "kern_util.h"
-+
-+extern syscall_handler_t sys_ni_syscall;
-+extern syscall_handler_t sys_exit;
-+extern syscall_handler_t sys_fork;
-+extern syscall_handler_t sys_creat;
-+extern syscall_handler_t sys_link;
-+extern syscall_handler_t sys_unlink;
-+extern syscall_handler_t sys_chdir;
-+extern syscall_handler_t sys_mknod;
-+extern syscall_handler_t sys_chmod;
-+extern syscall_handler_t sys_lchown16;
-+extern syscall_handler_t sys_ni_syscall;
-+extern syscall_handler_t sys_stat;
-+extern syscall_handler_t sys_getpid;
-+extern syscall_handler_t sys_oldumount;
-+extern syscall_handler_t sys_setuid16;
-+extern syscall_handler_t sys_getuid16;
-+extern syscall_handler_t sys_ptrace;
-+extern syscall_handler_t sys_alarm;
-+extern syscall_handler_t sys_fstat;
-+extern syscall_handler_t sys_pause;
-+extern syscall_handler_t sys_utime;
-+extern syscall_handler_t sys_ni_syscall;
-+extern syscall_handler_t sys_ni_syscall;
-+extern syscall_handler_t sys_access;
-+extern syscall_handler_t sys_nice;
-+extern syscall_handler_t sys_ni_syscall;
-+extern syscall_handler_t sys_sync;
-+extern syscall_handler_t sys_kill;
-+extern syscall_handler_t sys_rename;
-+extern syscall_handler_t sys_mkdir;
-+extern syscall_handler_t sys_rmdir;
-+extern syscall_handler_t sys_pipe;
-+extern syscall_handler_t sys_times;
-+extern syscall_handler_t sys_ni_syscall;
-+extern syscall_handler_t sys_brk;
-+extern syscall_handler_t sys_setgid16;
-+extern syscall_handler_t sys_getgid16;
-+extern syscall_handler_t sys_signal;
-+extern syscall_handler_t sys_geteuid16;
-+extern syscall_handler_t sys_getegid16;
-+extern syscall_handler_t sys_acct;
-+extern syscall_handler_t sys_umount;
-+extern syscall_handler_t sys_ni_syscall;
-+extern syscall_handler_t sys_ioctl;
-+extern syscall_handler_t sys_fcntl;
-+extern syscall_handler_t sys_ni_syscall;
-+extern syscall_handler_t sys_setpgid;
-+extern syscall_handler_t sys_ni_syscall;
-+extern syscall_handler_t sys_olduname;
-+extern syscall_handler_t sys_umask;
-+extern syscall_handler_t sys_chroot;
-+extern syscall_handler_t sys_ustat;
-+extern syscall_handler_t sys_dup2;
-+extern syscall_handler_t sys_getppid;
-+extern syscall_handler_t sys_getpgrp;
-+extern syscall_handler_t sys_sigaction;
-+extern syscall_handler_t sys_sgetmask;
-+extern syscall_handler_t sys_ssetmask;
-+extern syscall_handler_t sys_setreuid16;
-+extern syscall_handler_t sys_setregid16;
-+extern syscall_handler_t sys_sigsuspend;
-+extern syscall_handler_t sys_sigpending;
-+extern syscall_handler_t sys_sethostname;
-+extern syscall_handler_t sys_setrlimit;
-+extern syscall_handler_t sys_old_getrlimit;
-+extern syscall_handler_t sys_getrusage;
-+extern syscall_handler_t sys_gettimeofday;
-+extern syscall_handler_t sys_settimeofday;
-+extern syscall_handler_t sys_getgroups16;
-+extern syscall_handler_t sys_setgroups16;
-+extern syscall_handler_t sys_symlink;
-+extern syscall_handler_t sys_lstat;
-+extern syscall_handler_t sys_readlink;
-+extern syscall_handler_t sys_uselib;
-+extern syscall_handler_t sys_swapon;
-+extern syscall_handler_t sys_reboot;
-+extern syscall_handler_t old_readdir;
-+extern syscall_handler_t sys_munmap;
-+extern syscall_handler_t sys_truncate;
-+extern syscall_handler_t sys_ftruncate;
-+extern syscall_handler_t sys_fchmod;
-+extern syscall_handler_t sys_fchown16;
-+extern syscall_handler_t sys_getpriority;
-+extern syscall_handler_t sys_setpriority;
-+extern syscall_handler_t sys_ni_syscall;
-+extern syscall_handler_t sys_statfs;
-+extern syscall_handler_t sys_fstatfs;
-+extern syscall_handler_t sys_ni_syscall;
-+extern syscall_handler_t sys_socketcall;
-+extern syscall_handler_t sys_syslog;
-+extern syscall_handler_t sys_setitimer;
-+extern syscall_handler_t sys_getitimer;
-+extern syscall_handler_t sys_newstat;
-+extern syscall_handler_t sys_newlstat;
-+extern syscall_handler_t sys_newfstat;
-+extern syscall_handler_t sys_uname;
-+extern syscall_handler_t sys_ni_syscall;
-+extern syscall_handler_t sys_vhangup;
-+extern syscall_handler_t sys_ni_syscall;
-+extern syscall_handler_t sys_ni_syscall;
-+extern syscall_handler_t sys_swapoff;
-+extern syscall_handler_t sys_sysinfo;
-+extern syscall_handler_t sys_ipc;
-+extern syscall_handler_t sys_fsync;
-+extern syscall_handler_t sys_sigreturn;
-+extern syscall_handler_t sys_rt_sigreturn;
-+extern syscall_handler_t sys_clone;
-+extern syscall_handler_t sys_setdomainname;
-+extern syscall_handler_t sys_newuname;
-+extern syscall_handler_t sys_ni_syscall;
-+extern syscall_handler_t sys_adjtimex;
-+extern syscall_handler_t sys_mprotect;
-+extern syscall_handler_t sys_sigprocmask;
-+extern syscall_handler_t sys_create_module;
-+extern syscall_handler_t sys_init_module;
-+extern syscall_handler_t sys_delete_module;
-+extern syscall_handler_t sys_get_kernel_syms;
-+extern syscall_handler_t sys_quotactl;
-+extern syscall_handler_t sys_getpgid;
-+extern syscall_handler_t sys_fchdir;
-+extern syscall_handler_t sys_bdflush;
-+extern syscall_handler_t sys_sysfs;
-+extern syscall_handler_t sys_personality;
-+extern syscall_handler_t sys_ni_syscall;
-+extern syscall_handler_t sys_setfsuid16;
-+extern syscall_handler_t sys_setfsgid16;
-+extern syscall_handler_t sys_llseek;
-+extern syscall_handler_t sys_getdents;
-+extern syscall_handler_t sys_flock;
-+extern syscall_handler_t sys_msync;
-+extern syscall_handler_t sys_readv;
-+extern syscall_handler_t sys_writev;
-+extern syscall_handler_t sys_getsid;
-+extern syscall_handler_t sys_fdatasync;
-+extern syscall_handler_t sys_sysctl;
-+extern syscall_handler_t sys_mlock;
-+extern syscall_handler_t sys_munlock;
-+extern syscall_handler_t sys_mlockall;
-+extern syscall_handler_t sys_munlockall;
-+extern syscall_handler_t sys_sched_setparam;
-+extern syscall_handler_t sys_sched_getparam;
-+extern syscall_handler_t sys_sched_setscheduler;
-+extern syscall_handler_t sys_sched_getscheduler;
-+extern syscall_handler_t sys_sched_get_priority_max;
-+extern syscall_handler_t sys_sched_get_priority_min;
-+extern syscall_handler_t sys_sched_rr_get_interval;
-+extern syscall_handler_t sys_nanosleep;
-+extern syscall_handler_t sys_mremap;
-+extern syscall_handler_t sys_setresuid16;
-+extern syscall_handler_t sys_getresuid16;
-+extern syscall_handler_t sys_ni_syscall;
-+extern syscall_handler_t sys_query_module;
-+extern syscall_handler_t sys_poll;
-+extern syscall_handler_t sys_nfsservctl;
-+extern syscall_handler_t sys_setresgid16;
-+extern syscall_handler_t sys_getresgid16;
-+extern syscall_handler_t sys_prctl;
-+extern syscall_handler_t sys_ni_syscall;
-+extern syscall_handler_t sys_rt_sigaction;
-+extern syscall_handler_t sys_rt_sigprocmask;
-+extern syscall_handler_t sys_rt_sigpending;
-+extern syscall_handler_t sys_rt_sigtimedwait;
-+extern syscall_handler_t sys_rt_sigqueueinfo;
-+extern syscall_handler_t sys_rt_sigsuspend;
-+extern syscall_handler_t sys_pread;
-+extern syscall_handler_t sys_pwrite;
-+extern syscall_handler_t sys_chown16;
-+extern syscall_handler_t sys_getcwd;
-+extern syscall_handler_t sys_capget;
-+extern syscall_handler_t sys_capset;
-+extern syscall_handler_t sys_sigaltstack;
-+extern syscall_handler_t sys_sendfile;
-+extern syscall_handler_t sys_ni_syscall;
-+extern syscall_handler_t sys_ni_syscall;
-+extern syscall_handler_t sys_vfork;
-+extern syscall_handler_t sys_getrlimit;
-+extern syscall_handler_t sys_mmap2;
-+extern syscall_handler_t sys_truncate64;
-+extern syscall_handler_t sys_ftruncate64;
-+extern syscall_handler_t sys_stat64;
-+extern syscall_handler_t sys_lstat64;
-+extern syscall_handler_t sys_fstat64;
-+extern syscall_handler_t sys_lchown;
-+extern syscall_handler_t sys_getuid;
-+extern syscall_handler_t sys_getgid;
-+extern syscall_handler_t sys_geteuid;
-+extern syscall_handler_t sys_getegid;
-+extern syscall_handler_t sys_setreuid;
-+extern syscall_handler_t sys_setregid;
-+extern syscall_handler_t sys_getgroups;
-+extern syscall_handler_t sys_setgroups;
-+extern syscall_handler_t sys_fchown;
-+extern syscall_handler_t sys_setresuid;
-+extern syscall_handler_t sys_getresuid;
-+extern syscall_handler_t sys_setresgid;
-+extern syscall_handler_t sys_getresgid;
-+extern syscall_handler_t sys_chown;
-+extern syscall_handler_t sys_setuid;
-+extern syscall_handler_t sys_setgid;
-+extern syscall_handler_t sys_setfsuid;
-+extern syscall_handler_t sys_setfsgid;
-+extern syscall_handler_t sys_pivot_root;
-+extern syscall_handler_t sys_mincore;
-+extern syscall_handler_t sys_madvise;
-+extern syscall_handler_t sys_fcntl64;
-+extern syscall_handler_t sys_getdents64;
-+extern syscall_handler_t sys_gettid;
-+extern syscall_handler_t sys_readahead;
-+extern syscall_handler_t sys_tkill;
-+extern syscall_handler_t sys_setxattr;
-+extern syscall_handler_t sys_lsetxattr;
-+extern syscall_handler_t sys_fsetxattr;
-+extern syscall_handler_t sys_getxattr;
-+extern syscall_handler_t sys_lgetxattr;
-+extern syscall_handler_t sys_fgetxattr;
-+extern syscall_handler_t sys_listxattr;
-+extern syscall_handler_t sys_llistxattr;
-+extern syscall_handler_t sys_flistxattr;
-+extern syscall_handler_t sys_removexattr;
-+extern syscall_handler_t sys_lremovexattr;
-+extern syscall_handler_t sys_fremovexattr;
-+extern syscall_handler_t sys_sendfile64;
-+
-+extern syscall_handler_t um_mount;
-+extern syscall_handler_t um_time;
-+extern syscall_handler_t um_stime;
-+
-+#define LAST_GENERIC_SYSCALL __NR_exit_group
-+
-+#if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL
-+#define LAST_SYSCALL LAST_GENERIC_SYSCALL
-+#else
-+#define LAST_SYSCALL LAST_ARCH_SYSCALL
-+#endif
-+
-+syscall_handler_t *sys_call_table[] = {
-+ [ 0 ] = sys_ni_syscall,
-+ [ __NR_exit ] = sys_exit,
-+ [ __NR_fork ] = sys_fork,
-+ [ __NR_read ] = (syscall_handler_t *) sys_read,
-+ [ __NR_write ] = (syscall_handler_t *) sys_write,
-+
-+ /* These three are declared differently in asm/unistd.h */
-+ [ __NR_open ] = (syscall_handler_t *) sys_open,
-+ [ __NR_close ] = (syscall_handler_t *) sys_close,
-+ [ __NR_waitpid ] = (syscall_handler_t *) sys_waitpid,
-+ [ __NR_creat ] = sys_creat,
-+ [ __NR_link ] = sys_link,
-+ [ __NR_unlink ] = sys_unlink,
-+
-+ /* declared differently in kern_util.h */
-+ [ __NR_execve ] = (syscall_handler_t *) sys_execve,
-+ [ __NR_chdir ] = sys_chdir,
-+ [ __NR_time ] = um_time,
-+ [ __NR_mknod ] = sys_mknod,
-+ [ __NR_chmod ] = sys_chmod,
-+ [ __NR_lchown ] = sys_lchown16,
-+ [ __NR_break ] = sys_ni_syscall,
-+ [ __NR_oldstat ] = sys_stat,
-+ [ __NR_lseek ] = (syscall_handler_t *) sys_lseek,
-+ [ __NR_getpid ] = sys_getpid,
-+ [ __NR_mount ] = um_mount,
-+ [ __NR_umount ] = sys_oldumount,
-+ [ __NR_setuid ] = sys_setuid16,
-+ [ __NR_getuid ] = sys_getuid16,
-+ [ __NR_stime ] = um_stime,
-+ [ __NR_ptrace ] = sys_ptrace,
-+ [ __NR_alarm ] = sys_alarm,
-+ [ __NR_oldfstat ] = sys_fstat,
-+ [ __NR_pause ] = sys_pause,
-+ [ __NR_utime ] = sys_utime,
-+ [ __NR_stty ] = sys_ni_syscall,
-+ [ __NR_gtty ] = sys_ni_syscall,
-+ [ __NR_access ] = sys_access,
-+ [ __NR_nice ] = sys_nice,
-+ [ __NR_ftime ] = sys_ni_syscall,
-+ [ __NR_sync ] = sys_sync,
-+ [ __NR_kill ] = sys_kill,
-+ [ __NR_rename ] = sys_rename,
-+ [ __NR_mkdir ] = sys_mkdir,
-+ [ __NR_rmdir ] = sys_rmdir,
-+
-+ /* Declared differently in asm/unistd.h */
-+ [ __NR_dup ] = (syscall_handler_t *) sys_dup,
-+ [ __NR_pipe ] = sys_pipe,
-+ [ __NR_times ] = sys_times,
-+ [ __NR_prof ] = sys_ni_syscall,
-+ [ __NR_brk ] = sys_brk,
-+ [ __NR_setgid ] = sys_setgid16,
-+ [ __NR_getgid ] = sys_getgid16,
-+ [ __NR_signal ] = sys_signal,
-+ [ __NR_geteuid ] = sys_geteuid16,
-+ [ __NR_getegid ] = sys_getegid16,
-+ [ __NR_acct ] = sys_acct,
-+ [ __NR_umount2 ] = sys_umount,
-+ [ __NR_lock ] = sys_ni_syscall,
-+ [ __NR_ioctl ] = sys_ioctl,
-+ [ __NR_fcntl ] = sys_fcntl,
-+ [ __NR_mpx ] = sys_ni_syscall,
-+ [ __NR_setpgid ] = sys_setpgid,
-+ [ __NR_ulimit ] = sys_ni_syscall,
-+ [ __NR_oldolduname ] = sys_olduname,
-+ [ __NR_umask ] = sys_umask,
-+ [ __NR_chroot ] = sys_chroot,
-+ [ __NR_ustat ] = sys_ustat,
-+ [ __NR_dup2 ] = sys_dup2,
-+ [ __NR_getppid ] = sys_getppid,
-+ [ __NR_getpgrp ] = sys_getpgrp,
-+ [ __NR_setsid ] = (syscall_handler_t *) sys_setsid,
-+ [ __NR_sigaction ] = sys_sigaction,
-+ [ __NR_sgetmask ] = sys_sgetmask,
-+ [ __NR_ssetmask ] = sys_ssetmask,
-+ [ __NR_setreuid ] = sys_setreuid16,
-+ [ __NR_setregid ] = sys_setregid16,
-+ [ __NR_sigsuspend ] = sys_sigsuspend,
-+ [ __NR_sigpending ] = sys_sigpending,
-+ [ __NR_sethostname ] = sys_sethostname,
-+ [ __NR_setrlimit ] = sys_setrlimit,
-+ [ __NR_getrlimit ] = sys_old_getrlimit,
-+ [ __NR_getrusage ] = sys_getrusage,
-+ [ __NR_gettimeofday ] = sys_gettimeofday,
-+ [ __NR_settimeofday ] = sys_settimeofday,
-+ [ __NR_getgroups ] = sys_getgroups16,
-+ [ __NR_setgroups ] = sys_setgroups16,
-+ [ __NR_symlink ] = sys_symlink,
-+ [ __NR_oldlstat ] = sys_lstat,
-+ [ __NR_readlink ] = sys_readlink,
-+ [ __NR_uselib ] = sys_uselib,
-+ [ __NR_swapon ] = sys_swapon,
-+ [ __NR_reboot ] = sys_reboot,
-+ [ __NR_readdir ] = old_readdir,
-+ [ __NR_munmap ] = sys_munmap,
-+ [ __NR_truncate ] = sys_truncate,
-+ [ __NR_ftruncate ] = sys_ftruncate,
-+ [ __NR_fchmod ] = sys_fchmod,
-+ [ __NR_fchown ] = sys_fchown16,
-+ [ __NR_getpriority ] = sys_getpriority,
-+ [ __NR_setpriority ] = sys_setpriority,
-+ [ __NR_profil ] = sys_ni_syscall,
-+ [ __NR_statfs ] = sys_statfs,
-+ [ __NR_fstatfs ] = sys_fstatfs,
-+ [ __NR_ioperm ] = sys_ni_syscall,
-+ [ __NR_socketcall ] = sys_socketcall,
-+ [ __NR_syslog ] = sys_syslog,
-+ [ __NR_setitimer ] = sys_setitimer,
-+ [ __NR_getitimer ] = sys_getitimer,
-+ [ __NR_stat ] = sys_newstat,
-+ [ __NR_lstat ] = sys_newlstat,
-+ [ __NR_fstat ] = sys_newfstat,
-+ [ __NR_olduname ] = sys_uname,
-+ [ __NR_iopl ] = sys_ni_syscall,
-+ [ __NR_vhangup ] = sys_vhangup,
-+ [ __NR_idle ] = sys_ni_syscall,
-+ [ __NR_wait4 ] = (syscall_handler_t *) sys_wait4,
-+ [ __NR_swapoff ] = sys_swapoff,
-+ [ __NR_sysinfo ] = sys_sysinfo,
-+ [ __NR_ipc ] = sys_ipc,
-+ [ __NR_fsync ] = sys_fsync,
-+ [ __NR_sigreturn ] = sys_sigreturn,
-+ [ __NR_clone ] = sys_clone,
-+ [ __NR_setdomainname ] = sys_setdomainname,
-+ [ __NR_uname ] = sys_newuname,
-+ [ __NR_adjtimex ] = sys_adjtimex,
-+ [ __NR_mprotect ] = sys_mprotect,
-+ [ __NR_sigprocmask ] = sys_sigprocmask,
-+ [ __NR_create_module ] = sys_create_module,
-+ [ __NR_init_module ] = sys_init_module,
-+ [ __NR_delete_module ] = sys_delete_module,
-+ [ __NR_get_kernel_syms ] = sys_get_kernel_syms,
-+ [ __NR_quotactl ] = sys_quotactl,
-+ [ __NR_getpgid ] = sys_getpgid,
-+ [ __NR_fchdir ] = sys_fchdir,
-+ [ __NR_bdflush ] = sys_bdflush,
-+ [ __NR_sysfs ] = sys_sysfs,
-+ [ __NR_personality ] = sys_personality,
-+ [ __NR_afs_syscall ] = sys_ni_syscall,
-+ [ __NR_setfsuid ] = sys_setfsuid16,
-+ [ __NR_setfsgid ] = sys_setfsgid16,
-+ [ __NR__llseek ] = sys_llseek,
-+ [ __NR_getdents ] = sys_getdents,
-+ [ __NR__newselect ] = (syscall_handler_t *) sys_select,
-+ [ __NR_flock ] = sys_flock,
-+ [ __NR_msync ] = sys_msync,
-+ [ __NR_readv ] = sys_readv,
-+ [ __NR_writev ] = sys_writev,
-+ [ __NR_getsid ] = sys_getsid,
-+ [ __NR_fdatasync ] = sys_fdatasync,
-+ [ __NR__sysctl ] = sys_sysctl,
-+ [ __NR_mlock ] = sys_mlock,
-+ [ __NR_munlock ] = sys_munlock,
-+ [ __NR_mlockall ] = sys_mlockall,
-+ [ __NR_munlockall ] = sys_munlockall,
-+ [ __NR_sched_setparam ] = sys_sched_setparam,
-+ [ __NR_sched_getparam ] = sys_sched_getparam,
-+ [ __NR_sched_setscheduler ] = sys_sched_setscheduler,
-+ [ __NR_sched_getscheduler ] = sys_sched_getscheduler,
-+ [ __NR_sched_yield ] = (syscall_handler_t *) yield,
-+ [ __NR_sched_get_priority_max ] = sys_sched_get_priority_max,
-+ [ __NR_sched_get_priority_min ] = sys_sched_get_priority_min,
-+ [ __NR_sched_rr_get_interval ] = sys_sched_rr_get_interval,
-+ [ __NR_nanosleep ] = sys_nanosleep,
-+ [ __NR_mremap ] = sys_mremap,
-+ [ __NR_setresuid ] = sys_setresuid16,
-+ [ __NR_getresuid ] = sys_getresuid16,
-+ [ __NR_vm86 ] = sys_ni_syscall,
-+ [ __NR_query_module ] = sys_query_module,
-+ [ __NR_poll ] = sys_poll,
-+ [ __NR_nfsservctl ] = sys_nfsservctl,
-+ [ __NR_setresgid ] = sys_setresgid16,
-+ [ __NR_getresgid ] = sys_getresgid16,
-+ [ __NR_prctl ] = sys_prctl,
-+ [ __NR_rt_sigreturn ] = sys_rt_sigreturn,
-+ [ __NR_rt_sigaction ] = sys_rt_sigaction,
-+ [ __NR_rt_sigprocmask ] = sys_rt_sigprocmask,
-+ [ __NR_rt_sigpending ] = sys_rt_sigpending,
-+ [ __NR_rt_sigtimedwait ] = sys_rt_sigtimedwait,
-+ [ __NR_rt_sigqueueinfo ] = sys_rt_sigqueueinfo,
-+ [ __NR_rt_sigsuspend ] = sys_rt_sigsuspend,
-+ [ __NR_pread ] = sys_pread,
-+ [ __NR_pwrite ] = sys_pwrite,
-+ [ __NR_chown ] = sys_chown16,
-+ [ __NR_getcwd ] = sys_getcwd,
-+ [ __NR_capget ] = sys_capget,
-+ [ __NR_capset ] = sys_capset,
-+ [ __NR_sigaltstack ] = sys_sigaltstack,
-+ [ __NR_sendfile ] = sys_sendfile,
-+ [ __NR_getpmsg ] = sys_ni_syscall,
-+ [ __NR_putpmsg ] = sys_ni_syscall,
-+ [ __NR_vfork ] = sys_vfork,
-+ [ __NR_ugetrlimit ] = sys_getrlimit,
-+ [ __NR_mmap2 ] = sys_mmap2,
-+ [ __NR_truncate64 ] = sys_truncate64,
-+ [ __NR_ftruncate64 ] = sys_ftruncate64,
-+ [ __NR_stat64 ] = sys_stat64,
-+ [ __NR_lstat64 ] = sys_lstat64,
-+ [ __NR_fstat64 ] = sys_fstat64,
-+ [ __NR_fcntl64 ] = sys_fcntl64,
-+ [ __NR_getdents64 ] = sys_getdents64,
-+ [ __NR_security ] = sys_ni_syscall,
-+ [ __NR_gettid ] = sys_gettid,
-+ [ __NR_readahead ] = sys_readahead,
-+ [ __NR_setxattr ] = sys_setxattr,
-+ [ __NR_lsetxattr ] = sys_lsetxattr,
-+ [ __NR_fsetxattr ] = sys_fsetxattr,
-+ [ __NR_getxattr ] = sys_getxattr,
-+ [ __NR_lgetxattr ] = sys_lgetxattr,
-+ [ __NR_fgetxattr ] = sys_fgetxattr,
-+ [ __NR_listxattr ] = sys_listxattr,
-+ [ __NR_llistxattr ] = sys_llistxattr,
-+ [ __NR_flistxattr ] = sys_flistxattr,
-+ [ __NR_removexattr ] = sys_removexattr,
-+ [ __NR_lremovexattr ] = sys_lremovexattr,
-+ [ __NR_fremovexattr ] = sys_fremovexattr,
-+ [ __NR_tkill ] = sys_tkill,
-+ [ __NR_sendfile64 ] = sys_sendfile64,
-+ [ __NR_futex ] = sys_ni_syscall,
-+ [ __NR_sched_setaffinity ] = sys_ni_syscall,
-+ [ __NR_sched_getaffinity ] = sys_ni_syscall,
-+ [ __NR_set_thread_area ] = sys_ni_syscall,
-+ [ __NR_get_thread_area ] = sys_ni_syscall,
-+ [ __NR_io_setup ] = sys_ni_syscall,
-+ [ __NR_io_destroy ] = sys_ni_syscall,
-+ [ __NR_io_getevents ] = sys_ni_syscall,
-+ [ __NR_io_submit ] = sys_ni_syscall,
-+ [ __NR_io_cancel ] = sys_ni_syscall,
-+ [ __NR_alloc_hugepages ] = sys_ni_syscall,
-+ [ __NR_free_hugepages ] = sys_ni_syscall,
-+ [ __NR_exit_group ] = sys_ni_syscall,
-+
-+ ARCH_SYSCALLS
-+ [ LAST_SYSCALL + 1 ... NR_syscalls ] =
-+ (syscall_handler_t *) sys_ni_syscall
-+};
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/syscall_user.c um/arch/um/kernel/syscall_user.c
---- orig/arch/um/kernel/syscall_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/syscall_user.c 2003-12-22 01:32:48.000000000 -0500
-@@ -0,0 +1,48 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdlib.h>
-+#include <sys/time.h>
-+#include "kern_util.h"
-+#include "syscall_user.h"
-+
-+struct {
-+ int syscall;
-+ int pid;
-+ int result;
-+ struct timeval start;
-+ struct timeval end;
-+} syscall_record[1024];
-+
-+int record_syscall_start(int syscall)
-+{
-+ int max, index;
-+
-+ max = sizeof(syscall_record)/sizeof(syscall_record[0]);
-+ index = next_syscall_index(max);
-+
-+ syscall_record[index].syscall = syscall;
-+ syscall_record[index].pid = current_pid();
-+ syscall_record[index].result = 0xdeadbeef;
-+ gettimeofday(&syscall_record[index].start, NULL);
-+ return(index);
-+}
-+
-+void record_syscall_end(int index, int result)
-+{
-+ syscall_record[index].result = result;
-+ gettimeofday(&syscall_record[index].end, NULL);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/sysrq.c um/arch/um/kernel/sysrq.c
---- orig/arch/um/kernel/sysrq.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/sysrq.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,98 @@
-+/*
-+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/sched.h"
-+#include "linux/kernel.h"
-+#include "linux/module.h"
-+#include "asm/page.h"
-+#include "asm/processor.h"
-+#include "sysrq.h"
-+#include "user_util.h"
-+
-+ /*
-+ * If the address is either in the .text section of the
-+ * kernel, or in the vmalloc'ed module regions, it *may*
-+ * be the address of a calling routine
-+ */
-+
-+#ifdef CONFIG_MODULES
-+
-+extern struct module *module_list;
-+extern struct module kernel_module;
-+
-+static inline int kernel_text_address(unsigned long addr)
-+{
-+ int retval = 0;
-+ struct module *mod;
-+
-+ if (addr >= (unsigned long) &_stext &&
-+ addr <= (unsigned long) &_etext)
-+ return 1;
-+
-+ for (mod = module_list; mod != &kernel_module; mod = mod->next) {
-+ /* mod_bound tests for addr being inside the vmalloc'ed
-+ * module area. Of course it'd be better to test only
-+ * for the .text subset... */
-+ if (mod_bound(addr, 0, mod)) {
-+ retval = 1;
-+ break;
-+ }
-+ }
-+
-+ return retval;
-+}
-+
-+#else
-+
-+static inline int kernel_text_address(unsigned long addr)
-+{
-+ return (addr >= (unsigned long) &_stext &&
-+ addr <= (unsigned long) &_etext);
-+}
-+
-+#endif
-+
-+void show_trace(unsigned long * stack)
-+{
-+ int i;
-+ unsigned long addr;
-+
-+ if (!stack)
-+ stack = (unsigned long*) &stack;
-+
-+ printk("Call Trace: ");
-+ i = 1;
-+ while (((long) stack & (THREAD_SIZE-1)) != 0) {
-+ addr = *stack++;
-+ if (kernel_text_address(addr)) {
-+ if (i && ((i % 6) == 0))
-+ printk("\n ");
-+ printk("[<%08lx>] ", addr);
-+ i++;
-+ }
-+ }
-+ printk("\n");
-+}
-+
-+void show_trace_task(struct task_struct *tsk)
-+{
-+ unsigned long esp = PT_REGS_SP(&tsk->thread.regs);
-+
-+ /* User space on another CPU? */
-+ if ((esp ^ (unsigned long)tsk) & (PAGE_MASK<<1))
-+ return;
-+ show_trace((unsigned long *)esp);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tempfile.c um/arch/um/kernel/tempfile.c
---- orig/arch/um/kernel/tempfile.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tempfile.c 2003-12-22 01:33:38.000000000 -0500
-@@ -0,0 +1,82 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <string.h>
-+#include <errno.h>
-+#include <sys/param.h>
-+#include "init.h"
-+
-+/* Modified from create_mem_file and start_debugger */
-+static char *tempdir = NULL;
-+
-+static void __init find_tempdir(void)
-+{
-+ char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL };
-+ int i;
-+ char *dir = NULL;
-+
-+ if(tempdir != NULL) return; /* We've already been called */
-+ for(i = 0; dirs[i]; i++){
-+ dir = getenv(dirs[i]);
-+ if((dir != NULL) && (*dir != '\0'))
-+ break;
-+ }
-+ if((dir == NULL) || (*dir == '\0'))
-+ dir = "/tmp";
-+
-+ tempdir = malloc(strlen(dir) + 2);
-+ if(tempdir == NULL){
-+ fprintf(stderr, "Failed to malloc tempdir, "
-+ "errno = %d\n", errno);
-+ return;
-+ }
-+ strcpy(tempdir, dir);
-+ strcat(tempdir, "/");
-+}
-+
-+int make_tempfile(const char *template, char **out_tempname, int do_unlink)
-+{
-+ char tempname[MAXPATHLEN];
-+ int fd;
-+
-+ find_tempdir();
-+ if (*template != '/')
-+ strcpy(tempname, tempdir);
-+ else
-+ *tempname = 0;
-+ strcat(tempname, template);
-+ fd = mkstemp(tempname);
-+ if(fd < 0){
-+ fprintf(stderr, "open - cannot create %s: %s\n", tempname,
-+ strerror(errno));
-+ return -1;
-+ }
-+ if(do_unlink && (unlink(tempname) < 0)){
-+ perror("unlink");
-+ return -1;
-+ }
-+ if(out_tempname){
-+ *out_tempname = strdup(tempname);
-+ if(*out_tempname == NULL){
-+ perror("strdup");
-+ return -1;
-+ }
-+ }
-+ return(fd);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/time.c um/arch/um/kernel/time.c
---- orig/arch/um/kernel/time.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/time.c 2004-02-12 07:09:48.000000000 -0500
-@@ -0,0 +1,172 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <time.h>
-+#include <sys/time.h>
-+#include <signal.h>
-+#include <errno.h>
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "user.h"
-+#include "process.h"
-+#include "signal_user.h"
-+#include "time_user.h"
-+
-+extern struct timeval xtime;
-+
-+struct timeval local_offset = { 0, 0 };
-+
-+void timer(void)
-+{
-+ gettimeofday(&xtime, NULL);
-+ timeradd(&xtime, &local_offset, &xtime);
-+}
-+
-+void set_interval(int timer_type)
-+{
-+ int usec = 1000000/hz();
-+ struct itimerval interval = ((struct itimerval) { { 0, usec },
-+ { 0, usec } });
-+
-+ if(setitimer(timer_type, &interval, NULL) == -1)
-+ panic("setitimer failed - errno = %d\n", errno);
-+}
-+
-+void enable_timer(void)
-+{
-+ int usec = 1000000/hz();
-+ struct itimerval enable = ((struct itimerval) { { 0, usec },
-+ { 0, usec }});
-+ if(setitimer(ITIMER_VIRTUAL, &enable, NULL))
-+ printk("enable_timer - setitimer failed, errno = %d\n",
-+ errno);
-+}
-+
-+void switch_timers(int to_real)
-+{
-+ struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
-+ struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() },
-+ { 0, 1000000/hz() }});
-+ int old, new;
-+
-+ if(to_real){
-+ old = ITIMER_VIRTUAL;
-+ new = ITIMER_REAL;
-+ }
-+ else {
-+ old = ITIMER_REAL;
-+ new = ITIMER_VIRTUAL;
-+ }
-+
-+ if((setitimer(old, &disable, NULL) < 0) ||
-+ (setitimer(new, &enable, NULL)))
-+ printk("switch_timers - setitimer failed, errno = %d\n",
-+ errno);
-+}
-+
-+void idle_timer(void)
-+{
-+ if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR)
-+ panic("Couldn't unset SIGVTALRM handler");
-+
-+ set_handler(SIGALRM, (__sighandler_t) alarm_handler,
-+ SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
-+ set_interval(ITIMER_REAL);
-+}
-+
-+static unsigned long long get_host_hz(void)
-+{
-+ char mhzline[16], *end;
-+ unsigned long long mhz;
-+ int ret, mult, rest, len;
-+
-+ ret = cpu_feature("cpu MHz", mhzline,
-+ sizeof(mhzline) / sizeof(mhzline[0]));
-+ if(!ret)
-+ panic ("Could not get host MHZ");
-+
-+ mhz = strtoul(mhzline, &end, 10);
-+
-+ /* This business is to parse a floating point number without using
-+ * floating types.
-+ */
-+
-+ rest = 0;
-+ mult = 0;
-+ if(*end == '.'){
-+ end++;
-+ len = strlen(end);
-+ if(len < 6)
-+ mult = 6 - len;
-+ else if(len > 6)
-+ end[6] = '\0';
-+ rest = strtoul(end, NULL, 10);
-+ while(mult-- > 0)
-+ rest *= 10;
-+ }
-+
-+ return(1000000 * mhz + rest);
-+}
-+
-+unsigned long long host_hz = 0;
-+
-+void time_init(void)
-+{
-+ /* XXX This is to fill xtime with something real - otherwise by the
-+ * time /proc is mounted, no timers have fired, and xtime is still 0,
-+ * meaning it shows times of Jan 1 1970. The real fix is to figure
-+ * out why no timers have happened by then.
-+ */
-+ timer();
-+
-+ host_hz = get_host_hz();
-+ if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR)
-+ panic("Couldn't set SIGVTALRM handler");
-+ set_interval(ITIMER_VIRTUAL);
-+}
-+
-+void do_gettimeofday(struct timeval *tv)
-+{
-+ unsigned long flags;
-+
-+ flags = time_lock();
-+ gettimeofday(tv, NULL);
-+ timeradd(tv, &local_offset, tv);
-+ time_unlock(flags);
-+}
-+
-+void do_settimeofday(struct timeval *tv)
-+{
-+ struct timeval now;
-+ unsigned long flags;
-+
-+ flags = time_lock();
-+ gettimeofday(&now, NULL);
-+ timersub(tv, &now, &local_offset);
-+ time_unlock(flags);
-+}
-+
-+void idle_sleep(int secs)
-+{
-+ struct timespec ts;
-+
-+ ts.tv_sec = secs;
-+ ts.tv_nsec = 0;
-+ nanosleep(&ts, NULL);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/time_kern.c um/arch/um/kernel/time_kern.c
---- orig/arch/um/kernel/time_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/time_kern.c 2004-02-14 06:51:31.000000000 -0500
-@@ -0,0 +1,205 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/kernel.h"
-+#include "linux/unistd.h"
-+#include "linux/stddef.h"
-+#include "linux/spinlock.h"
-+#include "linux/sched.h"
-+#include "linux/interrupt.h"
-+#include "linux/init.h"
-+#include "linux/delay.h"
-+#include "asm/irq.h"
-+#include "asm/param.h"
-+#include "asm/current.h"
-+#include "kern_util.h"
-+#include "user_util.h"
-+#include "time_user.h"
-+#include "mode.h"
-+
-+extern rwlock_t xtime_lock;
-+
-+int hz(void)
-+{
-+ return(HZ);
-+}
-+
-+/* Changed at early boot */
-+int timer_irq_inited = 0;
-+
-+/* missed_ticks will be modified after kernel memory has been
-+ * write-protected, so this puts it in a section which will be left
-+ * write-enabled.
-+ */
-+int __attribute__ ((__section__ (".unprotected"))) missed_ticks[NR_CPUS];
-+
-+static int first_tick;
-+static unsigned long long prev_tsc;
-+static long long delta; /* Deviation per interval */
-+
-+extern unsigned long long host_hz;
-+
-+void timer_irq(union uml_pt_regs *regs)
-+{
-+ unsigned long long ticks = 0;
-+
-+ if(!timer_irq_inited){
-+ /* This is to ensure that ticks don't pile up when
-+ * the timer handler is suspended */
-+ first_tick = 0;
-+ return;
-+ }
-+
-+ if(first_tick){
-+#if defined(CONFIG_UML_REAL_TIME_CLOCK)
-+ unsigned long long tsc;
-+ /* We've had 1 tick */
-+ tsc = time_stamp();
-+
-+ delta += tsc - prev_tsc;
-+ prev_tsc = tsc;
-+
-+ ticks += (delta * HZ) / host_hz;
-+ delta -= (ticks * host_hz) / HZ;
-+#else
-+ ticks = 1;
-+#endif
-+ }
-+ else {
-+ prev_tsc = time_stamp();
-+ first_tick = 1;
-+ }
-+
-+ while(ticks > 0){
-+ do_IRQ(TIMER_IRQ, regs);
-+ ticks--;
-+ }
-+}
-+
-+void boot_timer_handler(int sig)
-+{
-+ struct pt_regs regs;
-+
-+ CHOOSE_MODE((void)
-+ (UPT_SC(®s.regs) = (struct sigcontext *) (&sig + 1)),
-+ (void) (regs.regs.skas.is_user = 0));
-+ do_timer(®s);
-+}
-+
-+void um_timer(int irq, void *dev, struct pt_regs *regs)
-+{
-+ do_timer(regs);
-+ write_lock(&xtime_lock);
-+ vxtime_lock();
-+ timer();
-+ vxtime_unlock();
-+ write_unlock(&xtime_lock);
-+}
-+
-+long um_time(int * tloc)
-+{
-+ struct timeval now;
-+
-+ do_gettimeofday(&now);
-+ if (tloc) {
-+ if (put_user(now.tv_sec,tloc))
-+ now.tv_sec = -EFAULT;
-+ }
-+ return now.tv_sec;
-+}
-+
-+long um_stime(int * tptr)
-+{
-+ int value;
-+ struct timeval new;
-+
-+ if (get_user(value, tptr))
-+ return -EFAULT;
-+ new.tv_sec = value;
-+ new.tv_usec = 0;
-+ do_settimeofday(&new);
-+ return 0;
-+}
-+
-+/* XXX Needs to be moved under sys-i386 */
-+void __delay(um_udelay_t time)
-+{
-+ /* Stolen from the i386 __loop_delay */
-+ int d0;
-+ __asm__ __volatile__(
-+ "\tjmp 1f\n"
-+ ".align 16\n"
-+ "1:\tjmp 2f\n"
-+ ".align 16\n"
-+ "2:\tdecl %0\n\tjns 2b"
-+ :"=&a" (d0)
-+ :"0" (time));
-+}
-+
-+void __udelay(um_udelay_t usecs)
-+{
-+ int i, n;
-+
-+ n = (loops_per_jiffy * HZ * usecs) / 1000000;
-+ for(i=0;i<n;i++) ;
-+}
-+
-+void __const_udelay(um_udelay_t usecs)
-+{
-+ int i, n;
-+
-+ n = (loops_per_jiffy * HZ * usecs) / 1000000;
-+ for(i=0;i<n;i++) ;
-+}
-+
-+void timer_handler(int sig, union uml_pt_regs *regs)
-+{
-+#ifdef CONFIG_SMP
-+ update_process_times(user_context(UPT_SP(regs)));
-+#endif
-+ if(current->processor == 0)
-+ timer_irq(regs);
-+}
-+
-+static spinlock_t timer_spinlock = SPIN_LOCK_UNLOCKED;
-+
-+unsigned long time_lock(void)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&timer_spinlock, flags);
-+ return(flags);
-+}
-+
-+void time_unlock(unsigned long flags)
-+{
-+ spin_unlock_irqrestore(&timer_spinlock, flags);
-+}
-+
-+int __init timer_init(void)
-+{
-+ int err;
-+
-+ CHOOSE_MODE(user_time_init_tt(), user_time_init_skas());
-+ err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer", NULL);
-+ if(err != 0)
-+ printk(KERN_ERR "timer_init : request_irq failed - "
-+ "errno = %d\n", -err);
-+ timer_irq_inited = 1;
-+ return(0);
-+}
-+
-+__initcall(timer_init);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tlb.c um/arch/um/kernel/tlb.c
---- orig/arch/um/kernel/tlb.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tlb.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,80 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/mm.h"
-+#include "asm/page.h"
-+#include "asm/pgalloc.h"
-+#include "choose-mode.h"
-+#include "mode_kern.h"
-+
-+void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
-+{
-+ address &= PAGE_MASK;
-+ flush_tlb_range(vma->vm_mm, address, address + PAGE_SIZE);
-+}
-+
-+void flush_tlb_all(void)
-+{
-+ flush_tlb_mm(current->mm);
-+}
-+
-+void flush_tlb_kernel_vm(void)
-+{
-+ CHOOSE_MODE(flush_tlb_kernel_vm_tt(), flush_tlb_kernel_vm_skas());
-+}
-+
-+void __flush_tlb_one(unsigned long addr)
-+{
-+ CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr);
-+}
-+
-+void flush_tlb_range(struct mm_struct *mm, unsigned long start,
-+ unsigned long end)
-+{
-+ CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, mm, start,
-+ end);
-+}
-+
-+void flush_tlb_mm(struct mm_struct *mm)
-+{
-+ CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm);
-+}
-+
-+void force_flush_all(void)
-+{
-+ CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas());
-+}
-+
-+
-+pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address)
-+{
-+ return(pgd_offset(mm, address));
-+}
-+
-+pmd_t *pmd_offset_proc(pgd_t *pgd, unsigned long address)
-+{
-+ return(pmd_offset(pgd, address));
-+}
-+
-+pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address)
-+{
-+ return(pte_offset(pmd, address));
-+}
-+
-+pte_t *addr_pte(struct task_struct *task, unsigned long addr)
-+{
-+ return(pte_offset(pmd_offset(pgd_offset(task->mm, addr), addr), addr));
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/trap_kern.c um/arch/um/kernel/trap_kern.c
---- orig/arch/um/kernel/trap_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/trap_kern.c 2003-12-22 22:48:41.000000000 -0500
-@@ -0,0 +1,220 @@
-+/*
-+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/kernel.h"
-+#include "linux/sched.h"
-+#include "linux/mm.h"
-+#include "linux/spinlock.h"
-+#include "linux/config.h"
-+#include "linux/init.h"
-+#include "asm/semaphore.h"
-+#include "asm/pgtable.h"
-+#include "asm/pgalloc.h"
-+#include "asm/a.out.h"
-+#include "asm/current.h"
-+#include "asm/irq.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "kern.h"
-+#include "chan_kern.h"
-+#include "mconsole_kern.h"
-+#include "2_5compat.h"
-+#include "mem.h"
-+#include "mem_kern.h"
-+
-+unsigned long handle_page_fault(unsigned long address, unsigned long ip,
-+ int is_write, int is_user, int *code_out)
-+{
-+ struct mm_struct *mm = current->mm;
-+ struct vm_area_struct *vma;
-+ pgd_t *pgd;
-+ pmd_t *pmd;
-+ pte_t *pte;
-+ unsigned long page;
-+ int handled = 0;
-+
-+ *code_out = SEGV_MAPERR;
-+ down_read(&mm->mmap_sem);
-+ vma = find_vma(mm, address);
-+ if(!vma)
-+ goto out;
-+ else if(vma->vm_start <= address)
-+ goto good_area;
-+ else if(!(vma->vm_flags & VM_GROWSDOWN))
-+ goto out;
-+ else if(expand_stack(vma, address))
-+ goto out;
-+
-+ good_area:
-+ *code_out = SEGV_ACCERR;
-+ if(is_write && !(vma->vm_flags & VM_WRITE))
-+ goto out;
-+ page = address & PAGE_MASK;
-+ if(page == (unsigned long) current + PAGE_SIZE)
-+ panic("Kernel stack overflow");
-+ pgd = pgd_offset(mm, page);
-+ pmd = pmd_offset(pgd, page);
-+ do {
-+ survive:
-+ switch (handle_mm_fault(mm, vma, address, is_write)) {
-+ case 1:
-+ current->min_flt++;
-+ break;
-+ case 2:
-+ current->maj_flt++;
-+ break;
-+ default:
-+ if (current->pid == 1) {
-+ up_read(&mm->mmap_sem);
-+ yield();
-+ down_read(&mm->mmap_sem);
-+ goto survive;
-+ }
-+ /* Fall through to bad area case */
-+ case 0:
-+ goto out;
-+ }
-+ pte = pte_offset(pmd, page);
-+ } while(!pte_present(*pte));
-+ handled = 1;
-+ *pte = pte_mkyoung(*pte);
-+ if(pte_write(*pte)) *pte = pte_mkdirty(*pte);
-+ flush_tlb_page(vma, page);
-+ out:
-+ up_read(&mm->mmap_sem);
-+ return(handled);
-+}
-+
-+LIST_HEAD(physmem_remappers);
-+
-+void register_remapper(struct remapper *info)
-+{
-+ list_add(&info->list, &physmem_remappers);
-+}
-+
-+static int check_remapped_addr(unsigned long address, int is_write)
-+{
-+ struct remapper *remapper;
-+ struct list_head *ele;
-+ __u64 offset;
-+ int fd;
-+
-+ fd = phys_mapping(__pa(address), &offset);
-+ if(fd == -1)
-+ return(0);
-+
-+ list_for_each(ele, &physmem_remappers){
-+ remapper = list_entry(ele, struct remapper, list);
-+ if((*remapper->proc)(fd, address, is_write, offset))
-+ return(1);
-+ }
-+
-+ return(0);
-+}
-+
-+unsigned long segv(unsigned long address, unsigned long ip, int is_write,
-+ int is_user, void *sc)
-+{
-+ struct siginfo si;
-+ void *catcher;
-+ int handled;
-+
-+ if(!is_user && (address >= start_vm) && (address < end_vm)){
-+ flush_tlb_kernel_vm();
-+ return(0);
-+ }
-+ else if(check_remapped_addr(address & PAGE_MASK, is_write))
-+ return(0);
-+ else if(current->mm == NULL)
-+ panic("Segfault with no mm");
-+
-+ handled = handle_page_fault(address, ip, is_write, is_user,
-+ &si.si_code);
-+
-+ catcher = current->thread.fault_catcher;
-+ if(handled)
-+ return(0);
-+ else if(catcher != NULL){
-+ current->thread.fault_addr = (void *) address;
-+ do_longjmp(catcher, 1);
-+ }
-+ else if(current->thread.fault_addr != NULL)
-+ panic("fault_addr set but no fault catcher");
-+ else if(arch_fixup(ip, sc))
-+ return(0);
-+
-+ if(!is_user)
-+ panic("Kernel mode fault at addr 0x%lx, ip 0x%lx",
-+ address, ip);
-+ si.si_signo = SIGSEGV;
-+ si.si_addr = (void *) address;
-+ current->thread.cr2 = address;
-+ current->thread.err = is_write;
-+ force_sig_info(SIGSEGV, &si, current);
-+ return(0);
-+}
-+
-+void bad_segv(unsigned long address, unsigned long ip, int is_write)
-+{
-+ struct siginfo si;
-+
-+ si.si_signo = SIGSEGV;
-+ si.si_code = SEGV_ACCERR;
-+ si.si_addr = (void *) address;
-+ current->thread.cr2 = address;
-+ current->thread.err = is_write;
-+ force_sig_info(SIGSEGV, &si, current);
-+}
-+
-+void relay_signal(int sig, union uml_pt_regs *regs)
-+{
-+ if(arch_handle_signal(sig, regs)) return;
-+ if(!UPT_IS_USER(regs))
-+ panic("Kernel mode signal %d", sig);
-+ force_sig(sig, current);
-+}
-+
-+void bus_handler(int sig, union uml_pt_regs *regs)
-+{
-+ if(current->thread.fault_catcher != NULL)
-+ do_longjmp(current->thread.fault_catcher, 1);
-+ else relay_signal(sig, regs);
-+}
-+
-+void winch(int sig, union uml_pt_regs *regs)
-+{
-+ do_IRQ(WINCH_IRQ, regs);
-+}
-+
-+void trap_init(void)
-+{
-+}
-+
-+spinlock_t trap_lock = SPIN_LOCK_UNLOCKED;
-+
-+static int trap_index = 0;
-+
-+int next_trap_index(int limit)
-+{
-+ int ret;
-+
-+ spin_lock(&trap_lock);
-+ ret = trap_index;
-+ if(++trap_index == limit)
-+ trap_index = 0;
-+ spin_unlock(&trap_lock);
-+ return(ret);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/trap_user.c um/arch/um/kernel/trap_user.c
---- orig/arch/um/kernel/trap_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/trap_user.c 2004-01-31 02:47:39.000000000 -0500
-@@ -0,0 +1,138 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdlib.h>
-+#include <errno.h>
-+#include <setjmp.h>
-+#include <signal.h>
-+#include <sys/time.h>
-+#include <sys/ptrace.h>
-+#include <sys/wait.h>
-+#include <asm/page.h>
-+#include <asm/unistd.h>
-+#include <asm/ptrace.h>
-+#include "init.h"
-+#include "sysdep/ptrace.h"
-+#include "sigcontext.h"
-+#include "sysdep/sigcontext.h"
-+#include "irq_user.h"
-+#include "frame_user.h"
-+#include "signal_user.h"
-+#include "time_user.h"
-+#include "task.h"
-+#include "mode.h"
-+#include "choose-mode.h"
-+#include "kern_util.h"
-+#include "user_util.h"
-+#include "os.h"
-+
-+void kill_child_dead(int pid)
-+{
-+ kill(pid, SIGKILL);
-+ kill(pid, SIGCONT);
-+ while(waitpid(pid, NULL, 0) > 0) kill(pid, SIGCONT);
-+}
-+
-+/* Unlocked - don't care if this is a bit off */
-+int nsegfaults = 0;
-+
-+struct {
-+ unsigned long address;
-+ int is_write;
-+ int pid;
-+ unsigned long sp;
-+ int is_user;
-+} segfault_record[1024];
-+
-+void segv_handler(int sig, union uml_pt_regs *regs)
-+{
-+ int index, max;
-+
-+ if(UPT_IS_USER(regs) && !UPT_SEGV_IS_FIXABLE(regs)){
-+ bad_segv(UPT_FAULT_ADDR(regs), UPT_IP(regs),
-+ UPT_FAULT_WRITE(regs));
-+ return;
-+ }
-+ max = sizeof(segfault_record)/sizeof(segfault_record[0]);
-+ index = next_trap_index(max);
-+
-+ nsegfaults++;
-+ segfault_record[index].address = UPT_FAULT_ADDR(regs);
-+ segfault_record[index].pid = os_getpid();
-+ segfault_record[index].is_write = UPT_FAULT_WRITE(regs);
-+ segfault_record[index].sp = UPT_SP(regs);
-+ segfault_record[index].is_user = UPT_IS_USER(regs);
-+ segv(UPT_FAULT_ADDR(regs), UPT_IP(regs), UPT_FAULT_WRITE(regs),
-+ UPT_IS_USER(regs), regs);
-+}
-+
-+void usr2_handler(int sig, union uml_pt_regs *regs)
-+{
-+ CHOOSE_MODE(syscall_handler_tt(sig, regs), (void) 0);
-+}
-+
-+struct signal_info sig_info[] = {
-+ [ SIGTRAP ] { .handler = relay_signal,
-+ .is_irq = 0 },
-+ [ SIGFPE ] { .handler = relay_signal,
-+ .is_irq = 0 },
-+ [ SIGILL ] { .handler = relay_signal,
-+ .is_irq = 0 },
-+ [ SIGWINCH ] { .handler = winch,
-+ .is_irq = 1 },
-+ [ SIGBUS ] { .handler = bus_handler,
-+ .is_irq = 0 },
-+ [ SIGSEGV] { .handler = segv_handler,
-+ .is_irq = 0 },
-+ [ SIGIO ] { .handler = sigio_handler,
-+ .is_irq = 1 },
-+ [ SIGVTALRM ] { .handler = timer_handler,
-+ .is_irq = 1 },
-+ [ SIGALRM ] { .handler = timer_handler,
-+ .is_irq = 1 },
-+ [ SIGUSR2 ] { .handler = usr2_handler,
-+ .is_irq = 0 },
-+};
-+
-+void sig_handler(int sig, struct sigcontext sc)
-+{
-+ CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
-+ sig, &sc);
-+}
-+
-+extern int timer_irq_inited, missed_ticks[];
-+
-+void alarm_handler(int sig, struct sigcontext sc)
-+{
-+ if(!timer_irq_inited) return;
-+ missed_ticks[cpu()]++;
-+
-+ if(sig == SIGALRM)
-+ switch_timers(0);
-+
-+ CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
-+ sig, &sc);
-+
-+ if(sig == SIGALRM)
-+ switch_timers(1);
-+}
-+
-+void do_longjmp(void *b, int val)
-+{
-+ sigjmp_buf *buf = b;
-+
-+ siglongjmp(*buf, val);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/exec_kern.c um/arch/um/kernel/tt/exec_kern.c
---- orig/arch/um/kernel/tt/exec_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/exec_kern.c 2003-11-07 02:23:10.000000000 -0500
-@@ -0,0 +1,84 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/kernel.h"
-+#include "linux/mm.h"
-+#include "asm/signal.h"
-+#include "asm/ptrace.h"
-+#include "asm/uaccess.h"
-+#include "asm/pgalloc.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "irq_user.h"
-+#include "time_user.h"
-+#include "mem_user.h"
-+#include "os.h"
-+#include "tlb.h"
-+#include "mode.h"
-+
-+static int exec_tramp(void *sig_stack)
-+{
-+ init_new_thread_stack(sig_stack, NULL);
-+ init_new_thread_signals(1);
-+ os_stop_process(os_getpid());
-+ return(0);
-+}
-+
-+void flush_thread_tt(void)
-+{
-+ unsigned long stack;
-+ int new_pid;
-+
-+ stack = alloc_stack(0, 0);
-+ if(stack == 0){
-+ printk(KERN_ERR
-+ "flush_thread : failed to allocate temporary stack\n");
-+ do_exit(SIGKILL);
-+ }
-+
-+ new_pid = start_fork_tramp((void *) current->thread.kernel_stack,
-+ stack, 0, exec_tramp);
-+ if(new_pid < 0){
-+ printk(KERN_ERR
-+ "flush_thread : new thread failed, errno = %d\n",
-+ -new_pid);
-+ do_exit(SIGKILL);
-+ }
-+
-+ if(current->processor == 0)
-+ forward_interrupts(new_pid);
-+ current->thread.request.op = OP_EXEC;
-+ current->thread.request.u.exec.pid = new_pid;
-+ unprotect_stack((unsigned long) current);
-+ os_usr1_process(os_getpid());
-+
-+ enable_timer();
-+ free_page(stack);
-+ protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1);
-+ task_protections((unsigned long) current);
-+ force_flush_all();
-+ unblock_signals();
-+}
-+
-+void start_thread_tt(struct pt_regs *regs, unsigned long eip,
-+ unsigned long esp)
-+{
-+ set_fs(USER_DS);
-+ flush_tlb_mm(current->mm);
-+ PT_REGS_IP(regs) = eip;
-+ PT_REGS_SP(regs) = esp;
-+ PT_FIX_EXEC_STACK(esp);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/exec_user.c um/arch/um/kernel/tt/exec_user.c
---- orig/arch/um/kernel/tt/exec_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/exec_user.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,49 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdio.h>
-+#include <unistd.h>
-+#include <stdlib.h>
-+#include <sched.h>
-+#include <errno.h>
-+#include <sys/wait.h>
-+#include <sys/ptrace.h>
-+#include <signal.h>
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "user.h"
-+#include "ptrace_user.h"
-+
-+void do_exec(int old_pid, int new_pid)
-+{
-+ unsigned long regs[FRAME_SIZE];
-+
-+ if((ptrace(PTRACE_ATTACH, new_pid, 0, 0) < 0) ||
-+ (ptrace(PTRACE_CONT, new_pid, 0, 0) < 0) ||
-+ (waitpid(new_pid, 0, WUNTRACED) < 0))
-+ tracer_panic("do_exec failed to attach proc - errno = %d",
-+ errno);
-+
-+ if(ptrace_getregs(old_pid, regs) < 0)
-+ tracer_panic("do_exec failed to get registers - errno = %d",
-+ errno);
-+
-+ kill(old_pid, SIGKILL);
-+
-+ if(ptrace_setregs(new_pid, regs) < 0)
-+ tracer_panic("do_exec failed to start new proc - errno = %d",
-+ errno);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/gdb.c um/arch/um/kernel/tt/gdb.c
---- orig/arch/um/kernel/tt/gdb.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/gdb.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,278 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <errno.h>
-+#include <string.h>
-+#include <signal.h>
-+#include <sys/ptrace.h>
-+#include <sys/types.h>
-+#include "uml-config.h"
-+#include "kern_constants.h"
-+#include "chan_user.h"
-+#include "init.h"
-+#include "user.h"
-+#include "debug.h"
-+#include "kern_util.h"
-+#include "user_util.h"
-+#include "tt.h"
-+#include "sysdep/thread.h"
-+
-+extern int debugger_pid;
-+extern int debugger_fd;
-+extern int debugger_parent;
-+
-+int detach(int pid, int sig)
-+{
-+ return(ptrace(PTRACE_DETACH, pid, 0, sig));
-+}
-+
-+int attach(int pid)
-+{
-+ int err;
-+
-+ err = ptrace(PTRACE_ATTACH, pid, 0, 0);
-+ if(err < 0) return(-errno);
-+ else return(err);
-+}
-+
-+int cont(int pid)
-+{
-+ return(ptrace(PTRACE_CONT, pid, 0, 0));
-+}
-+
-+#ifdef UML_CONFIG_PT_PROXY
-+
-+int debugger_signal(int status, pid_t pid)
-+{
-+ return(debugger_proxy(status, pid));
-+}
-+
-+void child_signal(pid_t pid, int status)
-+{
-+ child_proxy(pid, status);
-+}
-+
-+static void gdb_announce(char *dev_name, int dev)
-+{
-+ printf("gdb assigned device '%s'\n", dev_name);
-+}
-+
-+static struct chan_opts opts = {
-+ .announce = gdb_announce,
-+ .xterm_title = "UML kernel debugger",
-+ .raw = 0,
-+ .tramp_stack = 0,
-+ .in_kernel = 0,
-+};
-+
-+/* Accessed by the tracing thread, which automatically serializes access */
-+static void *xterm_data;
-+static int xterm_fd;
-+
-+extern void *xterm_init(char *, int, struct chan_opts *);
-+extern int xterm_open(int, int, int, void *, char **);
-+extern void xterm_close(int, void *);
-+
-+int open_gdb_chan(void)
-+{
-+ char stack[UM_KERN_PAGE_SIZE], *dummy;
-+
-+ opts.tramp_stack = (unsigned long) stack;
-+ xterm_data = xterm_init("", 0, &opts);
-+ xterm_fd = xterm_open(1, 1, 1, xterm_data, &dummy);
-+ return(xterm_fd);
-+}
-+
-+static void exit_debugger_cb(void *unused)
-+{
-+ if(debugger_pid != -1){
-+ if(gdb_pid != -1){
-+ fake_child_exit();
-+ gdb_pid = -1;
-+ }
-+ else kill_child_dead(debugger_pid);
-+ debugger_pid = -1;
-+ if(debugger_parent != -1)
-+ detach(debugger_parent, SIGINT);
-+ }
-+ if(xterm_data != NULL) xterm_close(xterm_fd, xterm_data);
-+}
-+
-+static void exit_debugger(void)
-+{
-+ initial_thread_cb(exit_debugger_cb, NULL);
-+}
-+
-+__uml_exitcall(exit_debugger);
-+
-+struct gdb_data {
-+ char *str;
-+ int err;
-+};
-+
-+static void config_gdb_cb(void *arg)
-+{
-+ struct gdb_data *data = arg;
-+ void *task;
-+ int pid;
-+
-+ data->err = -1;
-+ if(debugger_pid != -1) exit_debugger_cb(NULL);
-+ if(!strncmp(data->str, "pid,", strlen("pid,"))){
-+ data->str += strlen("pid,");
-+ pid = strtoul(data->str, NULL, 0);
-+ task = cpu_tasks[0].task;
-+ debugger_pid = attach_debugger(TASK_EXTERN_PID(task), pid, 0);
-+ if(debugger_pid != -1){
-+ data->err = 0;
-+ gdb_pid = pid;
-+ }
-+ return;
-+ }
-+ data->err = 0;
-+ debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd);
-+ init_proxy(debugger_pid, 0, 0);
-+}
-+
-+int gdb_config(char *str)
-+{
-+ struct gdb_data data;
-+
-+ if(*str++ != '=') return(-1);
-+ data.str = str;
-+ initial_thread_cb(config_gdb_cb, &data);
-+ return(data.err);
-+}
-+
-+void remove_gdb_cb(void *unused)
-+{
-+ exit_debugger_cb(NULL);
-+}
-+
-+int gdb_remove(char *unused)
-+{
-+ initial_thread_cb(remove_gdb_cb, NULL);
-+ return(0);
-+}
-+
-+void signal_usr1(int sig)
-+{
-+ if(debugger_pid != -1){
-+ printk(UM_KERN_ERR "The debugger is already running\n");
-+ return;
-+ }
-+ debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd);
-+ init_proxy(debugger_pid, 0, 0);
-+}
-+
-+int init_ptrace_proxy(int idle_pid, int startup, int stop)
-+{
-+ int pid, status;
-+
-+ pid = start_debugger(linux_prog, startup, stop, &debugger_fd);
-+ status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL);
-+ if(pid < 0){
-+ cont(idle_pid);
-+ return(-1);
-+ }
-+ init_proxy(pid, 1, status);
-+ return(pid);
-+}
-+
-+int attach_debugger(int idle_pid, int pid, int stop)
-+{
-+ int status = 0, err;
-+
-+ err = attach(pid);
-+ if(err < 0){
-+ printf("Failed to attach pid %d, errno = %d\n", pid, -err);
-+ return(-1);
-+ }
-+ if(stop) status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL);
-+ init_proxy(pid, 1, status);
-+ return(pid);
-+}
-+
-+#ifdef notdef /* Put this back in when it does something useful */
-+static int __init uml_gdb_init_setup(char *line, int *add)
-+{
-+ gdb_init = uml_strdup(line);
-+ return 0;
-+}
-+
-+__uml_setup("gdb=", uml_gdb_init_setup,
-+"gdb=<channel description>\n\n"
-+);
-+#endif
-+
-+static int __init uml_gdb_pid_setup(char *line, int *add)
-+{
-+ gdb_pid = strtoul(line, NULL, 0);
-+ *add = 0;
-+ return 0;
-+}
-+
-+__uml_setup("gdb-pid=", uml_gdb_pid_setup,
-+"gdb-pid=<pid>\n"
-+" gdb-pid is used to attach an external debugger to UML. This may be\n"
-+" an already-running gdb or a debugger-like process like strace.\n\n"
-+);
-+
-+#else
-+
-+int debugger_signal(int status, pid_t pid){ return(0); }
-+void child_signal(pid_t pid, int status){ }
-+int init_ptrace_proxy(int idle_pid, int startup, int stop)
-+{
-+ printk(UM_KERN_ERR "debug requested when CONFIG_PT_PROXY is off\n");
-+ kill_child_dead(idle_pid);
-+ exit(1);
-+}
-+
-+void signal_usr1(int sig)
-+{
-+ printk(UM_KERN_ERR "debug requested when CONFIG_PT_PROXY is off\n");
-+}
-+
-+int attach_debugger(int idle_pid, int pid, int stop)
-+{
-+ printk(UM_KERN_ERR "attach_debugger called when CONFIG_PT_PROXY "
-+ "is off\n");
-+ return(-1);
-+}
-+
-+int config_gdb(char *str)
-+{
-+ return(-1);
-+}
-+
-+int remove_gdb(void)
-+{
-+ return(-1);
-+}
-+
-+int init_parent_proxy(int pid)
-+{
-+ return(-1);
-+}
-+
-+void debugger_parent_signal(int status, int pid)
-+{
-+}
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/gdb_kern.c um/arch/um/kernel/tt/gdb_kern.c
---- orig/arch/um/kernel/tt/gdb_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/gdb_kern.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,40 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/init.h"
-+#include "linux/config.h"
-+#include "mconsole_kern.h"
-+
-+#ifdef CONFIG_MCONSOLE
-+
-+extern int gdb_config(char *str);
-+extern int gdb_remove(char *unused);
-+
-+static struct mc_device gdb_mc = {
-+ .name = "gdb",
-+ .config = gdb_config,
-+ .remove = gdb_remove,
-+};
-+
-+int gdb_mc_init(void)
-+{
-+ mconsole_register_dev(&gdb_mc);
-+ return(0);
-+}
-+
-+__initcall(gdb_mc_init);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/include/debug.h um/arch/um/kernel/tt/include/debug.h
---- orig/arch/um/kernel/tt/include/debug.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/include/debug.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,29 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) and
-+ * Lars Brinkhoff.
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __DEBUG_H
-+#define __DEBUG_H
-+
-+extern int debugger_proxy(int status, pid_t pid);
-+extern void child_proxy(pid_t pid, int status);
-+extern void init_proxy (pid_t pid, int waiting, int status);
-+extern int start_debugger(char *prog, int startup, int stop, int *debugger_fd);
-+extern void fake_child_exit(void);
-+extern int gdb_config(char *str);
-+extern int gdb_remove(char *unused);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/include/mmu.h um/arch/um/kernel/tt/include/mmu.h
---- orig/arch/um/kernel/tt/include/mmu.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/include/mmu.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,23 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __TT_MMU_H
-+#define __TT_MMU_H
-+
-+struct mmu_context_tt {
-+};
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/include/mode.h um/arch/um/kernel/tt/include/mode.h
---- orig/arch/um/kernel/tt/include/mode.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/include/mode.h 2003-11-07 01:42:09.000000000 -0500
-@@ -0,0 +1,38 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __MODE_TT_H__
-+#define __MODE_TT_H__
-+
-+#include "sysdep/ptrace.h"
-+
-+enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
-+
-+extern int tracing_pid;
-+
-+extern int tracer(int (*init_proc)(void *), void *sp);
-+extern void user_time_init_tt(void);
-+extern int copy_sc_from_user_tt(void *to_ptr, void *from_ptr, void *data);
-+extern int copy_sc_to_user_tt(void *to_ptr, void *fp, void *from_ptr,
-+ void *data);
-+extern void sig_handler_common_tt(int sig, void *sc);
-+extern void syscall_handler_tt(int sig, union uml_pt_regs *regs);
-+extern void reboot_tt(void);
-+extern void halt_tt(void);
-+extern int is_tracer_winch(int pid, int fd, void *data);
-+extern void kill_off_processes_tt(void);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/include/mode_kern.h um/arch/um/kernel/tt/include/mode_kern.h
---- orig/arch/um/kernel/tt/include/mode_kern.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/include/mode_kern.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,52 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __TT_MODE_KERN_H__
-+#define __TT_MODE_KERN_H__
-+
-+#include "linux/sched.h"
-+#include "asm/page.h"
-+#include "asm/ptrace.h"
-+#include "asm/uaccess.h"
-+
-+extern void *_switch_to_tt(void *prev, void *next);
-+extern void flush_thread_tt(void);
-+extern void start_thread_tt(struct pt_regs *regs, unsigned long eip,
-+ unsigned long esp);
-+extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
-+ unsigned long stack_top, struct task_struct *p,
-+ struct pt_regs *regs);
-+extern void release_thread_tt(struct task_struct *task);
-+extern void exit_thread_tt(void);
-+extern void initial_thread_cb_tt(void (*proc)(void *), void *arg);
-+extern void init_idle_tt(void);
-+extern void flush_tlb_kernel_vm_tt(void);
-+extern void __flush_tlb_one_tt(unsigned long addr);
-+extern void flush_tlb_range_tt(struct mm_struct *mm, unsigned long start,
-+ unsigned long end);
-+extern void flush_tlb_mm_tt(struct mm_struct *mm);
-+extern void force_flush_all_tt(void);
-+extern long execute_syscall_tt(void *r);
-+extern void before_mem_tt(unsigned long brk_start);
-+extern unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out,
-+ unsigned long *task_size_out);
-+extern int start_uml_tt(void);
-+extern int external_pid_tt(struct task_struct *task);
-+extern int thread_pid_tt(struct thread_struct *thread);
-+
-+#define kmem_end_tt (host_task_size - ABOVE_KMEM)
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/include/ptrace-tt.h um/arch/um/kernel/tt/include/ptrace-tt.h
---- orig/arch/um/kernel/tt/include/ptrace-tt.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/include/ptrace-tt.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,26 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __PTRACE_TT_H
-+#define __PTRACE_TT_H
-+
-+#include "uml-config.h"
-+
-+#ifdef UML_CONFIG_MODE_TT
-+#include "sysdep/sc.h"
-+#endif
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/include/tt.h um/arch/um/kernel/tt/include/tt.h
---- orig/arch/um/kernel/tt/include/tt.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/include/tt.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,46 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __TT_H__
-+#define __TT_H__
-+
-+#include "sysdep/ptrace.h"
-+
-+extern int gdb_pid;
-+extern int debug;
-+extern int debug_stop;
-+extern int debug_trace;
-+
-+extern int honeypot;
-+
-+extern int fork_tramp(void *sig_stack);
-+extern int do_proc_op(void *t, int proc_id);
-+extern int tracer(int (*init_proc)(void *), void *sp);
-+extern void attach_process(int pid);
-+extern void tracer_panic(char *format, ...);
-+extern void set_init_pid(int pid);
-+extern int set_user_mode(void *task);
-+extern void set_tracing(void *t, int tracing);
-+extern int is_tracing(void *task);
-+extern int singlestepping_tt(void *t);
-+extern void clear_singlestep(void *t);
-+extern void syscall_handler(int sig, union uml_pt_regs *regs);
-+extern void exit_kernel(int pid, void *task);
-+extern int do_syscall(void *task, int pid);
-+extern int is_valid_pid(int pid);
-+extern void remap_data(void *segment_start, void *segment_end, int w);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/include/uaccess.h um/arch/um/kernel/tt/include/uaccess.h
---- orig/arch/um/kernel/tt/include/uaccess.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/include/uaccess.h 2003-11-12 08:37:20.000000000 -0500
-@@ -0,0 +1,71 @@
-+/*
-+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __TT_UACCESS_H
-+#define __TT_UACCESS_H
-+
-+#include "linux/string.h"
-+#include "linux/sched.h"
-+#include "asm/processor.h"
-+#include "asm/errno.h"
-+#include "asm/current.h"
-+#include "asm/a.out.h"
-+#include "uml_uaccess.h"
-+
-+#define ABOVE_KMEM (16 * 1024 * 1024)
-+
-+extern unsigned long end_vm;
-+extern unsigned long uml_physmem;
-+
-+#define under_task_size(addr, size) \
-+ (((unsigned long) (addr) < TASK_SIZE) && \
-+ (((unsigned long) (addr) + (size)) < TASK_SIZE))
-+
-+#define is_stack(addr, size) \
-+ (((unsigned long) (addr) < STACK_TOP) && \
-+ ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \
-+ (((unsigned long) (addr) + (size)) <= STACK_TOP))
-+
-+#define access_ok_tt(type, addr, size) \
-+ ((type == VERIFY_READ) || (segment_eq(get_fs(), KERNEL_DS)) || \
-+ (((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \
-+ (under_task_size(addr, size) || is_stack(addr, size))))
-+
-+static inline int verify_area_tt(int type, const void * addr,
-+ unsigned long size)
-+{
-+ return(access_ok_tt(type, addr, size) ? 0 : -EFAULT);
-+}
-+
-+extern unsigned long get_fault_addr(void);
-+
-+extern int __do_copy_from_user(void *to, const void *from, int n,
-+ void **fault_addr, void **fault_catcher);
-+extern int __do_strncpy_from_user(char *dst, const char *src, size_t n,
-+ void **fault_addr, void **fault_catcher);
-+extern int __do_clear_user(void *mem, size_t len, void **fault_addr,
-+ void **fault_catcher);
-+extern int __do_strnlen_user(const char *str, unsigned long n,
-+ void **fault_addr, void **fault_catcher);
-+
-+extern int copy_from_user_tt(void *to, const void *from, int n);
-+extern int copy_to_user_tt(void *to, const void *from, int n);
-+extern int strncpy_from_user_tt(char *dst, const char *src, int count);
-+extern int __clear_user_tt(void *mem, int len);
-+extern int clear_user_tt(void *mem, int len);
-+extern int strnlen_user_tt(const void *str, int len);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/ksyms.c um/arch/um/kernel/tt/ksyms.c
---- orig/arch/um/kernel/tt/ksyms.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/ksyms.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,28 @@
-+/*
-+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/module.h"
-+#include "asm/uaccess.h"
-+#include "mode.h"
-+
-+EXPORT_SYMBOL(__do_copy_from_user);
-+EXPORT_SYMBOL(__do_copy_to_user);
-+EXPORT_SYMBOL(__do_strncpy_from_user);
-+EXPORT_SYMBOL(__do_strnlen_user);
-+EXPORT_SYMBOL(__do_clear_user);
-+
-+EXPORT_SYMBOL(tracing_pid);
-+EXPORT_SYMBOL(honeypot);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/Makefile um/arch/um/kernel/tt/Makefile
---- orig/arch/um/kernel/tt/Makefile 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/Makefile 2003-11-12 08:34:27.000000000 -0500
-@@ -0,0 +1,39 @@
-+#
-+# Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
-+# Licensed under the GPL
-+#
-+
-+O_TARGET = tt.o
-+
-+obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \
-+ syscall_kern.o syscall_user.o time.o tlb.o tracer.o trap_user.o \
-+ uaccess.o uaccess_user.o
-+
-+obj-$(CONFIG_PT_PROXY) += gdb_kern.o
-+
-+subdir-y = sys-$(SUBARCH)
-+subdir-$(CONFIG_PT_PROXY) += ptproxy
-+
-+obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
-+
-+export-objs = ksyms.o
-+
-+USER_OBJS = $(filter %_user.o,$(obj-y)) gdb.o time.o tracer.o
-+
-+UNMAP_CFLAGS := $(patsubst -pg -DPROFILING,,$(USER_CFLAGS))
-+UNMAP_CFLAGS := $(patsubst -fprofile-arcs -ftest-coverage,,$(UNMAP_CFLAGS))
-+
-+include $(TOPDIR)/Rules.make
-+
-+$(USER_OBJS) : %.o: %.c
-+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $<
-+
-+$(O_TARGET) : unmap_fin.o
-+
-+unmap.o: unmap.c
-+ $(CC) $(UNMAP_CFLAGS) -c -o $@ $<
-+
-+unmap_fin.o : unmap.o
-+ ld -r -o $@ $< -lc -L/usr/lib
-+
-+clean :
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/mem.c um/arch/um/kernel/tt/mem.c
---- orig/arch/um/kernel/tt/mem.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/mem.c 2004-01-31 02:38:28.000000000 -0500
-@@ -0,0 +1,51 @@
-+/*
-+ * Copyright (C) 2002 - 2004 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/stddef.h"
-+#include "linux/config.h"
-+#include "linux/mm.h"
-+#include "asm/uaccess.h"
-+#include "mem_user.h"
-+#include "kern_util.h"
-+#include "user_util.h"
-+#include "kern.h"
-+#include "tt.h"
-+
-+void before_mem_tt(unsigned long brk_start)
-+{
-+ if(!jail || debug)
-+ remap_data(UML_ROUND_DOWN(&_stext), UML_ROUND_UP(&_etext), 1);
-+ remap_data(UML_ROUND_DOWN(&_sdata), UML_ROUND_UP(&_edata), 1);
-+ remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(&_end), 1);
-+}
-+
-+#ifdef CONFIG_HOST_2G_2G
-+#define TOP 0x80000000
-+#else
-+#define TOP 0xc0000000
-+#endif
-+
-+#define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000)
-+#define START (TOP - SIZE)
-+
-+unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out,
-+ unsigned long *task_size_out)
-+{
-+ /* Round up to the nearest 4M */
-+ *host_size_out = ROUND_4M((unsigned long) &arg);
-+ *task_size_out = START;
-+ return(START);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/mem_user.c um/arch/um/kernel/tt/mem_user.c
---- orig/arch/um/kernel/tt/mem_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/mem_user.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,49 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdlib.h>
-+#include <stdio.h>
-+#include <unistd.h>
-+#include <string.h>
-+#include <errno.h>
-+#include <sys/mman.h>
-+#include "tt.h"
-+#include "mem_user.h"
-+#include "user_util.h"
-+
-+void remap_data(void *segment_start, void *segment_end, int w)
-+{
-+ void *addr;
-+ unsigned long size;
-+ int data, prot;
-+
-+ if(w) prot = PROT_WRITE;
-+ else prot = 0;
-+ prot |= PROT_READ | PROT_EXEC;
-+ size = (unsigned long) segment_end -
-+ (unsigned long) segment_start;
-+ data = create_mem_file(size);
-+ addr = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, data, 0);
-+ if(addr == MAP_FAILED){
-+ perror("mapping new data segment");
-+ exit(1);
-+ }
-+ memcpy(addr, segment_start, size);
-+ if(switcheroo(data, prot, addr, segment_start, size) < 0){
-+ printf("switcheroo failed\n");
-+ exit(1);
-+ }
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/process_kern.c um/arch/um/kernel/tt/process_kern.c
---- orig/arch/um/kernel/tt/process_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/process_kern.c 2004-01-31 02:39:08.000000000 -0500
-@@ -0,0 +1,535 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/sched.h"
-+#include "linux/signal.h"
-+#include "linux/kernel.h"
-+#include "asm/system.h"
-+#include "asm/pgalloc.h"
-+#include "asm/ptrace.h"
-+#include "irq_user.h"
-+#include "signal_user.h"
-+#include "kern_util.h"
-+#include "user_util.h"
-+#include "os.h"
-+#include "kern.h"
-+#include "sigcontext.h"
-+#include "time_user.h"
-+#include "mem_user.h"
-+#include "tlb.h"
-+#include "mode.h"
-+#include "init.h"
-+#include "tt.h"
-+
-+void *_switch_to_tt(void *prev, void *next)
-+{
-+ struct task_struct *from, *to;
-+ unsigned long flags;
-+ int err, vtalrm, alrm, prof, cpu;
-+ char c;
-+ /* jailing and SMP are incompatible, so this doesn't need to be
-+ * made per-cpu
-+ */
-+ static int reading;
-+
-+ from = prev;
-+ to = next;
-+
-+ to->thread.prev_sched = from;
-+
-+ cpu = from->processor;
-+ if(cpu == 0)
-+ forward_interrupts(to->thread.mode.tt.extern_pid);
-+#ifdef CONFIG_SMP
-+ forward_ipi(cpu_data[cpu].ipi_pipe[0], to->thread.mode.tt.extern_pid);
-+#endif
-+ local_irq_save(flags);
-+
-+ vtalrm = change_sig(SIGVTALRM, 0);
-+ alrm = change_sig(SIGALRM, 0);
-+ prof = change_sig(SIGPROF, 0);
-+
-+ c = 0;
-+ set_current(to);
-+
-+ reading = 0;
-+ err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c));
-+ if(err != sizeof(c))
-+ panic("write of switch_pipe failed, err = %d", -err);
-+
-+ reading = 1;
-+ if(from->state == TASK_ZOMBIE)
-+ os_kill_process(os_getpid(), 0);
-+
-+ err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c));
-+ if(err != sizeof(c))
-+ panic("read of switch_pipe failed, errno = %d", -err);
-+
-+ /* This works around a nasty race with 'jail'. If we are switching
-+ * between two threads of a threaded app and the incoming process
-+ * runs before the outgoing process reaches the read, and it makes
-+ * it all the way out to userspace, then it will have write-protected
-+ * the outgoing process stack. Then, when the outgoing process
-+ * returns from the write, it will segfault because it can no longer
-+ * write its own stack. So, in order to avoid that, the incoming
-+ * thread sits in a loop yielding until 'reading' is set. This
-+ * isn't entirely safe, since there may be a reschedule from a timer
-+ * happening between setting 'reading' and sleeping in read. But,
-+ * it should get a whole quantum in which to reach the read and sleep,
-+ * which should be enough.
-+ */
-+
-+ if(jail){
-+ while(!reading) sched_yield();
-+ }
-+
-+ change_sig(SIGVTALRM, vtalrm);
-+ change_sig(SIGALRM, alrm);
-+ change_sig(SIGPROF, prof);
-+
-+ arch_switch();
-+
-+ flush_tlb_all();
-+ local_irq_restore(flags);
-+
-+ return(current->thread.prev_sched);
-+}
-+
-+void release_thread_tt(struct task_struct *task)
-+{
-+ os_kill_process(task->thread.mode.tt.extern_pid, 0);
-+}
-+
-+void exit_thread_tt(void)
-+{
-+ os_close_file(current->thread.mode.tt.switch_pipe[0]);
-+ os_close_file(current->thread.mode.tt.switch_pipe[1]);
-+}
-+
-+extern void schedule_tail(struct task_struct *prev);
-+
-+static void new_thread_handler(int sig)
-+{
-+ unsigned long disable;
-+ int (*fn)(void *);
-+ void *arg;
-+
-+ fn = current->thread.request.u.thread.proc;
-+ arg = current->thread.request.u.thread.arg;
-+
-+ UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1);
-+ disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) |
-+ (1 << (SIGIO - 1)) | (1 << (SIGPROF - 1));
-+ SC_SIGMASK(UPT_SC(¤t->thread.regs.regs)) &= ~disable;
-+
-+ suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
-+
-+ init_new_thread_signals(1);
-+ enable_timer();
-+ free_page(current->thread.temp_stack);
-+ set_cmdline("(kernel thread)");
-+ force_flush_all();
-+
-+ if(current->thread.prev_sched != NULL)
-+ schedule_tail(current->thread.prev_sched);
-+ current->thread.prev_sched = NULL;
-+
-+ change_sig(SIGUSR1, 1);
-+ change_sig(SIGVTALRM, 1);
-+ change_sig(SIGPROF, 1);
-+ sti();
-+ if(!run_kernel_thread(fn, arg, ¤t->thread.exec_buf))
-+ do_exit(0);
-+}
-+
-+static int new_thread_proc(void *stack)
-+{
-+ /* cli is needed to block out signals until this thread is properly
-+ * scheduled. Otherwise, the tracing thread will get mighty upset
-+ * about any signals that arrive before that.
-+ * This has the complication that it sets the saved signal mask in
-+ * the sigcontext to block signals. This gets restored when this
-+ * thread (or a descendant, since they get a copy of this sigcontext)
-+ * returns to userspace.
-+ * So, this is compensated for elsewhere.
-+ * XXX There is still a small window until cli() actually finishes
-+ * where signals are possible - shouldn't be a problem in practice
-+ * since SIGIO hasn't been forwarded here yet, and the cli should
-+ * finish before a SIGVTALRM has time to be delivered.
-+ */
-+ cli();
-+ init_new_thread_stack(stack, new_thread_handler);
-+ os_usr1_process(os_getpid());
-+ return(0);
-+}
-+
-+/* Signal masking - signals are blocked at the start of fork_tramp. They
-+ * are re-enabled when finish_fork_handler is entered by fork_tramp hitting
-+ * itself with a SIGUSR1. set_user_mode has to be run with SIGUSR1 off,
-+ * so it is blocked before it's called. They are re-enabled on sigreturn
-+ * despite the fact that they were blocked when the SIGUSR1 was issued because
-+ * copy_thread copies the parent's sigcontext, including the signal mask
-+ * onto the signal frame.
-+ */
-+
-+static void finish_fork_handler(int sig)
-+{
-+ UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1);
-+ suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
-+
-+ init_new_thread_signals(1);
-+ enable_timer();
-+ sti();
-+ force_flush_all();
-+ if(current->mm != current->p_pptr->mm)
-+ protect_memory(uml_reserved, high_physmem - uml_reserved, 1,
-+ 1, 0, 1);
-+ task_protections((unsigned long) current);
-+
-+ if(current->thread.prev_sched != NULL)
-+ schedule_tail(current->thread.prev_sched);
-+ current->thread.prev_sched = NULL;
-+
-+ free_page(current->thread.temp_stack);
-+ cli();
-+ change_sig(SIGUSR1, 0);
-+ set_user_mode(current);
-+}
-+
-+int fork_tramp(void *stack)
-+{
-+ cli();
-+ arch_init_thread();
-+ init_new_thread_stack(stack, finish_fork_handler);
-+ os_usr1_process(os_getpid());
-+ return(0);
-+}
-+
-+int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
-+ unsigned long stack_top, struct task_struct * p,
-+ struct pt_regs *regs)
-+{
-+ int (*tramp)(void *);
-+ int new_pid, err;
-+ unsigned long stack;
-+
-+ if(current->thread.forking)
-+ tramp = fork_tramp;
-+ else {
-+ tramp = new_thread_proc;
-+ p->thread.request.u.thread = current->thread.request.u.thread;
-+ }
-+
-+ err = os_pipe(p->thread.mode.tt.switch_pipe, 1, 1);
-+ if(err < 0){
-+ printk("copy_thread : pipe failed, err = %d\n", -err);
-+ return(err);
-+ }
-+
-+ stack = alloc_stack(0, 0);
-+ if(stack == 0){
-+ printk(KERN_ERR "copy_thread : failed to allocate "
-+ "temporary stack\n");
-+ return(-ENOMEM);
-+ }
-+
-+ clone_flags &= CLONE_VM;
-+ p->thread.temp_stack = stack;
-+ new_pid = start_fork_tramp((void *) p->thread.kernel_stack, stack,
-+ clone_flags, tramp);
-+ if(new_pid < 0){
-+ printk(KERN_ERR "copy_thread : clone failed - errno = %d\n",
-+ -new_pid);
-+ return(new_pid);
-+ }
-+
-+ if(current->thread.forking){
-+ sc_to_sc(UPT_SC(&p->thread.regs.regs),
-+ UPT_SC(¤t->thread.regs.regs));
-+ SC_SET_SYSCALL_RETURN(UPT_SC(&p->thread.regs.regs), 0);
-+ if(sp != 0) SC_SP(UPT_SC(&p->thread.regs.regs)) = sp;
-+ }
-+ p->thread.mode.tt.extern_pid = new_pid;
-+
-+ current->thread.request.op = OP_FORK;
-+ current->thread.request.u.fork.pid = new_pid;
-+ os_usr1_process(os_getpid());
-+ return(0);
-+}
-+
-+void reboot_tt(void)
-+{
-+ current->thread.request.op = OP_REBOOT;
-+ os_usr1_process(os_getpid());
-+}
-+
-+void halt_tt(void)
-+{
-+ current->thread.request.op = OP_HALT;
-+ os_usr1_process(os_getpid());
-+}
-+
-+void kill_off_processes_tt(void)
-+{
-+ struct task_struct *p;
-+ int me;
-+
-+ me = os_getpid();
-+ for_each_task(p){
-+ int pid = p->thread.mode.tt.extern_pid;
-+ if((pid != me) && (pid != -1))
-+ os_kill_process(p->thread.mode.tt.extern_pid, 0);
-+ }
-+ if((init_task.thread.mode.tt.extern_pid != me) &&
-+ (init_task.thread.mode.tt.extern_pid != -1))
-+ os_kill_process(init_task.thread.mode.tt.extern_pid, 0);
-+}
-+
-+void initial_thread_cb_tt(void (*proc)(void *), void *arg)
-+{
-+ if(os_getpid() == tracing_pid){
-+ (*proc)(arg);
-+ }
-+ else {
-+ current->thread.request.op = OP_CB;
-+ current->thread.request.u.cb.proc = proc;
-+ current->thread.request.u.cb.arg = arg;
-+ os_usr1_process(os_getpid());
-+ }
-+}
-+
-+int do_proc_op(void *t, int proc_id)
-+{
-+ struct task_struct *task;
-+ struct thread_struct *thread;
-+ int op, pid;
-+
-+ task = t;
-+ thread = &task->thread;
-+ op = thread->request.op;
-+ switch(op){
-+ case OP_NONE:
-+ case OP_TRACE_ON:
-+ break;
-+ case OP_EXEC:
-+ pid = thread->request.u.exec.pid;
-+ do_exec(thread->mode.tt.extern_pid, pid);
-+ thread->mode.tt.extern_pid = pid;
-+ cpu_tasks[task->processor].pid = pid;
-+ break;
-+ case OP_FORK:
-+ attach_process(thread->request.u.fork.pid);
-+ break;
-+ case OP_CB:
-+ (*thread->request.u.cb.proc)(thread->request.u.cb.arg);
-+ break;
-+ case OP_REBOOT:
-+ case OP_HALT:
-+ break;
-+ default:
-+ tracer_panic("Bad op in do_proc_op");
-+ break;
-+ }
-+ thread->request.op = OP_NONE;
-+ return(op);
-+}
-+
-+void init_idle_tt(void)
-+{
-+ idle_timer();
-+}
-+
-+/* Changed by jail_setup, which is a setup */
-+int jail = 0;
-+
-+int __init jail_setup(char *line, int *add)
-+{
-+ int ok = 1;
-+
-+ if(jail) return(0);
-+#ifdef CONFIG_SMP
-+ printf("'jail' may not used used in a kernel with CONFIG_SMP "
-+ "enabled\n");
-+ ok = 0;
-+#endif
-+#ifdef CONFIG_HOSTFS
-+ printf("'jail' may not used used in a kernel with CONFIG_HOSTFS "
-+ "enabled\n");
-+ ok = 0;
-+#endif
-+#ifdef CONFIG_MODULES
-+ printf("'jail' may not used used in a kernel with CONFIG_MODULES "
-+ "enabled\n");
-+ ok = 0;
-+#endif
-+ if(!ok) exit(1);
-+
-+ /* CAP_SYS_RAWIO controls the ability to open /dev/mem and /dev/kmem.
-+ * Removing it from the bounding set eliminates the ability of anything
-+ * to acquire it, and thus read or write kernel memory.
-+ */
-+ cap_lower(cap_bset, CAP_SYS_RAWIO);
-+ jail = 1;
-+ return(0);
-+}
-+
-+__uml_setup("jail", jail_setup,
-+"jail\n"
-+" Enables the protection of kernel memory from processes.\n\n"
-+);
-+
-+static void mprotect_kernel_mem(int w)
-+{
-+ unsigned long start, end;
-+ int pages;
-+
-+ if(!jail || (current == &init_task)) return;
-+
-+ pages = (1 << CONFIG_KERNEL_STACK_ORDER);
-+
-+ start = (unsigned long) current + PAGE_SIZE;
-+ end = (unsigned long) current + PAGE_SIZE * pages;
-+ protect_memory(uml_reserved, start - uml_reserved, 1, w, 1, 1);
-+ protect_memory(end, high_physmem - end, 1, w, 1, 1);
-+
-+ start = (unsigned long) UML_ROUND_DOWN(&_stext);
-+ end = (unsigned long) UML_ROUND_UP(&_etext);
-+ protect_memory(start, end - start, 1, w, 1, 1);
-+
-+ start = (unsigned long) UML_ROUND_DOWN(&_unprotected_end);
-+ end = (unsigned long) UML_ROUND_UP(&_edata);
-+ protect_memory(start, end - start, 1, w, 1, 1);
-+
-+ start = (unsigned long) UML_ROUND_DOWN(&__bss_start);
-+ end = (unsigned long) UML_ROUND_UP(&_end);
-+ protect_memory(start, end - start, 1, w, 1, 1);
-+
-+ mprotect_kernel_vm(w);
-+}
-+
-+void unprotect_kernel_mem(void)
-+{
-+ mprotect_kernel_mem(1);
-+}
-+
-+void protect_kernel_mem(void)
-+{
-+ mprotect_kernel_mem(0);
-+}
-+
-+extern void start_kernel(void);
-+
-+static int start_kernel_proc(void *unused)
-+{
-+ int pid;
-+
-+ block_signals();
-+ pid = os_getpid();
-+
-+ cpu_tasks[0].pid = pid;
-+ cpu_tasks[0].task = current;
-+#ifdef CONFIG_SMP
-+ cpu_online_map = 1;
-+#endif
-+ if(debug) os_stop_process(pid);
-+ start_kernel();
-+ return(0);
-+}
-+
-+void set_tracing(void *task, int tracing)
-+{
-+ ((struct task_struct *) task)->thread.mode.tt.tracing = tracing;
-+}
-+
-+int is_tracing(void *t)
-+{
-+ return (((struct task_struct *) t)->thread.mode.tt.tracing);
-+}
-+
-+int set_user_mode(void *t)
-+{
-+ struct task_struct *task;
-+
-+ task = t ? t : current;
-+ if(task->thread.mode.tt.tracing)
-+ return(1);
-+ task->thread.request.op = OP_TRACE_ON;
-+ os_usr1_process(os_getpid());
-+ return(0);
-+}
-+
-+void set_init_pid(int pid)
-+{
-+ int err;
-+
-+ init_task.thread.mode.tt.extern_pid = pid;
-+ err = os_pipe(init_task.thread.mode.tt.switch_pipe, 1, 1);
-+ if(err)
-+ panic("Can't create switch pipe for init_task, errno = %d",
-+ -err);
-+}
-+
-+int singlestepping_tt(void *t)
-+{
-+ struct task_struct *task = t;
-+
-+ if(task->thread.mode.tt.singlestep_syscall)
-+ return(0);
-+ return(task->ptrace & PT_DTRACE);
-+}
-+
-+void clear_singlestep(void *t)
-+{
-+ struct task_struct *task = t;
-+
-+ task->ptrace &= ~PT_DTRACE;
-+}
-+
-+int start_uml_tt(void)
-+{
-+ void *sp;
-+ int pages;
-+
-+ pages = (1 << CONFIG_KERNEL_STACK_ORDER) - 2;
-+ sp = (void *) init_task.thread.kernel_stack + pages * PAGE_SIZE -
-+ sizeof(unsigned long);
-+ return(tracer(start_kernel_proc, sp));
-+}
-+
-+int external_pid_tt(struct task_struct *task)
-+{
-+ return(task->thread.mode.tt.extern_pid);
-+}
-+
-+int thread_pid_tt(struct thread_struct *thread)
-+{
-+ return(thread->mode.tt.extern_pid);
-+}
-+
-+int is_valid_pid(int pid)
-+{
-+ struct task_struct *task;
-+
-+ read_lock(&tasklist_lock);
-+ for_each_task(task){
-+ if(task->thread.mode.tt.extern_pid == pid){
-+ read_unlock(&tasklist_lock);
-+ return(1);
-+ }
-+ }
-+ read_unlock(&tasklist_lock);
-+ return(0);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/Makefile um/arch/um/kernel/tt/ptproxy/Makefile
---- orig/arch/um/kernel/tt/ptproxy/Makefile 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/ptproxy/Makefile 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,12 @@
-+O_TARGET = ptproxy.o
-+
-+obj-y = proxy.o ptrace.o sysdep.o wait.o
-+
-+USER_OBJS = $(obj-y)
-+
-+include $(TOPDIR)/Rules.make
-+
-+$(USER_OBJS) : %.o: %.c
-+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $<
-+
-+clean:
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/proxy.c um/arch/um/kernel/tt/ptproxy/proxy.c
---- orig/arch/um/kernel/tt/ptproxy/proxy.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/ptproxy/proxy.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,371 @@
-+/**********************************************************************
-+proxy.c
-+
-+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
-+terms and conditions.
-+
-+Jeff Dike (jdike@karaya.com) : Modified for integration into uml
-+**********************************************************************/
-+
-+/* XXX This file shouldn't refer to CONFIG_* */
-+
-+#include <errno.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <signal.h>
-+#include <string.h>
-+#include <termios.h>
-+#include <sys/wait.h>
-+#include <sys/types.h>
-+#include <sys/ptrace.h>
-+#include <sys/ioctl.h>
-+#include <asm/unistd.h>
-+
-+#include "ptproxy.h"
-+#include "sysdep.h"
-+#include "wait.h"
-+
-+#include "user_util.h"
-+#include "user.h"
-+#include "os.h"
-+#include "tempfile.h"
-+
-+static int debugger_wait(debugger_state *debugger, int *status, int options,
-+ int (*syscall)(debugger_state *debugger, pid_t child),
-+ int (*normal_return)(debugger_state *debugger,
-+ pid_t unused),
-+ int (*wait_return)(debugger_state *debugger,
-+ pid_t unused))
-+{
-+ if(debugger->real_wait){
-+ debugger->handle_trace = normal_return;
-+ syscall_continue(debugger->pid);
-+ debugger->real_wait = 0;
-+ return(1);
-+ }
-+ debugger->wait_status_ptr = status;
-+ debugger->wait_options = options;
-+ if((debugger->debugee != NULL) && debugger->debugee->event){
-+ syscall_continue(debugger->pid);
-+ wait_for_stop(debugger->pid, SIGTRAP, PTRACE_SYSCALL,
-+ NULL);
-+ (*wait_return)(debugger, -1);
-+ return(0);
-+ }
-+ else if(debugger->wait_options & WNOHANG){
-+ syscall_cancel(debugger->pid, 0);
-+ debugger->handle_trace = syscall;
-+ return(0);
-+ }
-+ else {
-+ syscall_pause(debugger->pid);
-+ debugger->handle_trace = wait_return;
-+ debugger->waiting = 1;
-+ }
-+ return(1);
-+}
-+
-+/*
-+ * Handle debugger trap, i.e. syscall.
-+ */
-+
-+int debugger_syscall(debugger_state *debugger, pid_t child)
-+{
-+ long arg1, arg2, arg3, arg4, arg5, result;
-+ int syscall, ret = 0;
-+
-+ syscall = get_syscall(debugger->pid, &arg1, &arg2, &arg3, &arg4,
-+ &arg5);
-+
-+ switch(syscall){
-+ case __NR_execve:
-+ /* execve never returns */
-+ debugger->handle_trace = debugger_syscall;
-+ break;
-+
-+ case __NR_ptrace:
-+ if(debugger->debugee->pid != 0) arg2 = debugger->debugee->pid;
-+ if(!debugger->debugee->in_context)
-+ child = debugger->debugee->pid;
-+ result = proxy_ptrace(debugger, arg1, arg2, arg3, arg4, child,
-+ &ret);
-+ syscall_cancel(debugger->pid, result);
-+ debugger->handle_trace = debugger_syscall;
-+ return(ret);
-+
-+ case __NR_waitpid:
-+ case __NR_wait4:
-+ if(!debugger_wait(debugger, (int *) arg2, arg3,
-+ debugger_syscall, debugger_normal_return,
-+ proxy_wait_return))
-+ return(0);
-+ break;
-+
-+ case __NR_kill:
-+ if(!debugger->debugee->in_context)
-+ child = debugger->debugee->pid;
-+ if(arg1 == debugger->debugee->pid){
-+ result = kill(child, arg2);
-+ syscall_cancel(debugger->pid, result);
-+ debugger->handle_trace = debugger_syscall;
-+ return(0);
-+ }
-+ else debugger->handle_trace = debugger_normal_return;
-+ break;
-+
-+ default:
-+ debugger->handle_trace = debugger_normal_return;
-+ }
-+
-+ syscall_continue(debugger->pid);
-+ return(0);
-+}
-+
-+/* Used by the tracing thread */
-+static debugger_state parent;
-+static int parent_syscall(debugger_state *debugger, int pid);
-+
-+int init_parent_proxy(int pid)
-+{
-+ parent = ((debugger_state) { .pid = pid,
-+ .wait_options = 0,
-+ .wait_status_ptr = NULL,
-+ .waiting = 0,
-+ .real_wait = 0,
-+ .expecting_child = 0,
-+ .handle_trace = parent_syscall,
-+ .debugee = NULL } );
-+ return(0);
-+}
-+
-+int parent_normal_return(debugger_state *debugger, pid_t unused)
-+{
-+ debugger->handle_trace = parent_syscall;
-+ syscall_continue(debugger->pid);
-+ return(0);
-+}
-+
-+static int parent_syscall(debugger_state *debugger, int pid)
-+{
-+ long arg1, arg2, arg3, arg4, arg5;
-+ int syscall;
-+
-+ syscall = get_syscall(pid, &arg1, &arg2, &arg3, &arg4, &arg5);
-+
-+ if((syscall == __NR_waitpid) || (syscall == __NR_wait4)){
-+ debugger_wait(&parent, (int *) arg2, arg3, parent_syscall,
-+ parent_normal_return, parent_wait_return);
-+ }
-+ else ptrace(PTRACE_SYSCALL, pid, 0, 0);
-+ return(0);
-+}
-+
-+int debugger_normal_return(debugger_state *debugger, pid_t unused)
-+{
-+ debugger->handle_trace = debugger_syscall;
-+ syscall_continue(debugger->pid);
-+ return(0);
-+}
-+
-+void debugger_cancelled_return(debugger_state *debugger, int result)
-+{
-+ debugger->handle_trace = debugger_syscall;
-+ syscall_set_result(debugger->pid, result);
-+ syscall_continue(debugger->pid);
-+}
-+
-+/* Used by the tracing thread */
-+static debugger_state debugger;
-+static debugee_state debugee;
-+
-+void init_proxy (pid_t debugger_pid, int stopped, int status)
-+{
-+ debugger.pid = debugger_pid;
-+ debugger.handle_trace = debugger_syscall;
-+ debugger.debugee = &debugee;
-+ debugger.waiting = 0;
-+ debugger.real_wait = 0;
-+ debugger.expecting_child = 0;
-+
-+ debugee.pid = 0;
-+ debugee.traced = 0;
-+ debugee.stopped = stopped;
-+ debugee.event = 0;
-+ debugee.zombie = 0;
-+ debugee.died = 0;
-+ debugee.wait_status = status;
-+ debugee.in_context = 1;
-+}
-+
-+int debugger_proxy(int status, int pid)
-+{
-+ int ret = 0, sig;
-+
-+ if(WIFSTOPPED(status)){
-+ sig = WSTOPSIG(status);
-+ if (sig == SIGTRAP)
-+ ret = (*debugger.handle_trace)(&debugger, pid);
-+
-+ else if(sig == SIGCHLD){
-+ if(debugger.expecting_child){
-+ ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig);
-+ debugger.expecting_child = 0;
-+ }
-+ else if(debugger.waiting)
-+ real_wait_return(&debugger);
-+ else {
-+ ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig);
-+ debugger.real_wait = 1;
-+ }
-+ }
-+ else ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig);
-+ }
-+ else if(WIFEXITED(status)){
-+ tracer_panic("debugger (pid %d) exited with status %d",
-+ debugger.pid, WEXITSTATUS(status));
-+ }
-+ else if(WIFSIGNALED(status)){
-+ tracer_panic("debugger (pid %d) exited with signal %d",
-+ debugger.pid, WTERMSIG(status));
-+ }
-+ else {
-+ tracer_panic("proxy got unknown status (0x%x) on debugger "
-+ "(pid %d)", status, debugger.pid);
-+ }
-+ return(ret);
-+}
-+
-+void child_proxy(pid_t pid, int status)
-+{
-+ debugee.event = 1;
-+ debugee.wait_status = status;
-+
-+ if(WIFSTOPPED(status)){
-+ debugee.stopped = 1;
-+ debugger.expecting_child = 1;
-+ kill(debugger.pid, SIGCHLD);
-+ }
-+ else if(WIFEXITED(status) || WIFSIGNALED(status)){
-+ debugee.zombie = 1;
-+ debugger.expecting_child = 1;
-+ kill(debugger.pid, SIGCHLD);
-+ }
-+ else panic("proxy got unknown status (0x%x) on child (pid %d)",
-+ status, pid);
-+}
-+
-+void debugger_parent_signal(int status, int pid)
-+{
-+ int sig;
-+
-+ if(WIFSTOPPED(status)){
-+ sig = WSTOPSIG(status);
-+ if(sig == SIGTRAP) (*parent.handle_trace)(&parent, pid);
-+ else ptrace(PTRACE_SYSCALL, pid, 0, sig);
-+ }
-+}
-+
-+void fake_child_exit(void)
-+{
-+ int status, pid;
-+
-+ child_proxy(1, W_EXITCODE(0, 0));
-+ while(debugger.waiting == 1){
-+ pid = waitpid(debugger.pid, &status, WUNTRACED);
-+ if(pid != debugger.pid){
-+ printk("fake_child_exit - waitpid failed, "
-+ "errno = %d\n", errno);
-+ return;
-+ }
-+ debugger_proxy(status, debugger.pid);
-+ }
-+ pid = waitpid(debugger.pid, &status, WUNTRACED);
-+ if(pid != debugger.pid){
-+ printk("fake_child_exit - waitpid failed, "
-+ "errno = %d\n", errno);
-+ return;
-+ }
-+ if(ptrace(PTRACE_DETACH, debugger.pid, 0, SIGCONT) < 0)
-+ printk("fake_child_exit - PTRACE_DETACH failed, errno = %d\n",
-+ errno);
-+}
-+
-+char gdb_init_string[] =
-+"att 1 \n\
-+b panic \n\
-+b stop \n\
-+handle SIGWINCH nostop noprint pass \n\
-+";
-+
-+int start_debugger(char *prog, int startup, int stop, int *fd_out)
-+{
-+ int slave, child;
-+
-+ slave = open_gdb_chan();
-+ child = fork();
-+ if(child == 0){
-+ char *tempname = NULL;
-+ int fd;
-+
-+ if(setsid() < 0) perror("setsid");
-+ if((dup2(slave, 0) < 0) || (dup2(slave, 1) < 0) ||
-+ (dup2(slave, 2) < 0)){
-+ printk("start_debugger : dup2 failed, errno = %d\n",
-+ errno);
-+ exit(1);
-+ }
-+ if(ioctl(0, TIOCSCTTY, 0) < 0){
-+ printk("start_debugger : TIOCSCTTY failed, "
-+ "errno = %d\n", errno);
-+ exit(1);
-+ }
-+ if(tcsetpgrp (1, os_getpid()) < 0){
-+ printk("start_debugger : tcsetpgrp failed, "
-+ "errno = %d\n", errno);
-+#ifdef notdef
-+ exit(1);
-+#endif
-+ }
-+ fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0);
-+ if(fd < 0){
-+ printk("start_debugger : make_tempfile failed,"
-+ "err = %d\n", -fd);
-+ exit(1);
-+ }
-+ os_write_file(fd, gdb_init_string, sizeof(gdb_init_string) - 1);
-+ if(startup){
-+ if(stop){
-+ os_write_file(fd, "b start_kernel\n",
-+ strlen("b start_kernel\n"));
-+ }
-+ os_write_file(fd, "c\n", strlen("c\n"));
-+ }
-+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){
-+ printk("start_debugger : PTRACE_TRACEME failed, "
-+ "errno = %d\n", errno);
-+ exit(1);
-+ }
-+ execlp("gdb", "gdb", "--command", tempname, prog, NULL);
-+ printk("start_debugger : exec of gdb failed, errno = %d\n",
-+ errno);
-+ }
-+ if(child < 0){
-+ printk("start_debugger : fork for gdb failed, errno = %d\n",
-+ errno);
-+ return(-1);
-+ }
-+ *fd_out = slave;
-+ return(child);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/ptproxy.h um/arch/um/kernel/tt/ptproxy/ptproxy.h
---- orig/arch/um/kernel/tt/ptproxy/ptproxy.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/ptproxy/ptproxy.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,61 @@
-+/**********************************************************************
-+ptproxy.h
-+
-+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
-+terms and conditions.
-+**********************************************************************/
-+
-+#ifndef __PTPROXY_H
-+#define __PTPROXY_H
-+
-+#include <sys/types.h>
-+
-+typedef struct debugger debugger_state;
-+typedef struct debugee debugee_state;
-+
-+struct debugger
-+{
-+ pid_t pid;
-+ int wait_options;
-+ int *wait_status_ptr;
-+ unsigned int waiting : 1;
-+ unsigned int real_wait : 1;
-+ unsigned int expecting_child : 1;
-+ int (*handle_trace) (debugger_state *, pid_t);
-+
-+ debugee_state *debugee;
-+};
-+
-+struct debugee
-+{
-+ pid_t pid;
-+ int wait_status;
-+ unsigned int died : 1;
-+ unsigned int event : 1;
-+ unsigned int stopped : 1;
-+ unsigned int trace_singlestep : 1;
-+ unsigned int trace_syscall : 1;
-+ unsigned int traced : 1;
-+ unsigned int zombie : 1;
-+ unsigned int in_context : 1;
-+};
-+
-+extern int debugger_syscall(debugger_state *debugger, pid_t pid);
-+extern int debugger_normal_return (debugger_state *debugger, pid_t unused);
-+
-+extern long proxy_ptrace (struct debugger *, int, pid_t, long, long, pid_t,
-+ int *strace_out);
-+extern void debugger_cancelled_return(debugger_state *debugger, int result);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/ptrace.c um/arch/um/kernel/tt/ptproxy/ptrace.c
---- orig/arch/um/kernel/tt/ptproxy/ptrace.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/ptproxy/ptrace.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,239 @@
-+/**********************************************************************
-+ptrace.c
-+
-+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
-+terms and conditions.
-+
-+Jeff Dike (jdike@karaya.com) : Modified for integration into uml
-+**********************************************************************/
-+
-+#include <errno.h>
-+#include <unistd.h>
-+#include <signal.h>
-+#include <sys/types.h>
-+#include <sys/time.h>
-+#include <sys/ptrace.h>
-+#include <sys/wait.h>
-+#include <asm/ptrace.h>
-+
-+#include "ptproxy.h"
-+#include "debug.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "ptrace_user.h"
-+#include "tt.h"
-+
-+long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2,
-+ long arg3, long arg4, pid_t child, int *ret)
-+{
-+ sigset_t relay;
-+ long result;
-+ int status;
-+
-+ *ret = 0;
-+ if(debugger->debugee->died) return(-ESRCH);
-+
-+ switch(arg1){
-+ case PTRACE_ATTACH:
-+ if(debugger->debugee->traced) return(-EPERM);
-+
-+ debugger->debugee->pid = arg2;
-+ debugger->debugee->traced = 1;
-+
-+ if(is_valid_pid(arg2) && (arg2 != child)){
-+ debugger->debugee->in_context = 0;
-+ kill(arg2, SIGSTOP);
-+ debugger->debugee->event = 1;
-+ debugger->debugee->wait_status = W_STOPCODE(SIGSTOP);
-+ }
-+ else {
-+ debugger->debugee->in_context = 1;
-+ if(debugger->debugee->stopped)
-+ child_proxy(child, W_STOPCODE(SIGSTOP));
-+ else kill(child, SIGSTOP);
-+ }
-+
-+ return(0);
-+
-+ case PTRACE_DETACH:
-+ if(!debugger->debugee->traced) return(-EPERM);
-+
-+ debugger->debugee->traced = 0;
-+ debugger->debugee->pid = 0;
-+ if(!debugger->debugee->in_context)
-+ kill(child, SIGCONT);
-+
-+ return(0);
-+
-+ case PTRACE_CONT:
-+ if(!debugger->debugee->in_context) return(-EPERM);
-+ *ret = PTRACE_CONT;
-+ return(ptrace(PTRACE_CONT, child, arg3, arg4));
-+
-+#ifdef UM_HAVE_GETFPREGS
-+ case PTRACE_GETFPREGS:
-+ {
-+ long regs[FP_FRAME_SIZE];
-+ int i, result;
-+
-+ result = ptrace(PTRACE_GETFPREGS, child, 0, regs);
-+ if(result == -1) return(-errno);
-+
-+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
-+ ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i,
-+ regs[i]);
-+ return(result);
-+ }
-+#endif
-+
-+#ifdef UM_HAVE_GETFPXREGS
-+ case PTRACE_GETFPXREGS:
-+ {
-+ long regs[FPX_FRAME_SIZE];
-+ int i, result;
-+
-+ result = ptrace(PTRACE_GETFPXREGS, child, 0, regs);
-+ if(result == -1) return(-errno);
-+
-+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
-+ ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i,
-+ regs[i]);
-+ return(result);
-+ }
-+#endif
-+
-+#ifdef UM_HAVE_GETREGS
-+ case PTRACE_GETREGS:
-+ {
-+ long regs[FRAME_SIZE];
-+ int i, result;
-+
-+ result = ptrace(PTRACE_GETREGS, child, 0, regs);
-+ if(result == -1) return(-errno);
-+
-+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
-+ ptrace (PTRACE_POKEDATA, debugger->pid,
-+ arg4 + 4 * i, regs[i]);
-+ return(result);
-+ }
-+ break;
-+#endif
-+
-+ case PTRACE_KILL:
-+ result = ptrace(PTRACE_KILL, child, arg3, arg4);
-+ if(result == -1) return(-errno);
-+
-+ return(result);
-+
-+ case PTRACE_PEEKDATA:
-+ case PTRACE_PEEKTEXT:
-+ case PTRACE_PEEKUSER:
-+ /* The value being read out could be -1, so we have to
-+ * check errno to see if there's an error, and zero it
-+ * beforehand so we're not faked out by an old error
-+ */
-+
-+ errno = 0;
-+ result = ptrace(arg1, child, arg3, 0);
-+ if((result == -1) && (errno != 0)) return(-errno);
-+
-+ result = ptrace(PTRACE_POKEDATA, debugger->pid, arg4, result);
-+ if(result == -1) return(-errno);
-+
-+ return(result);
-+
-+ case PTRACE_POKEDATA:
-+ case PTRACE_POKETEXT:
-+ case PTRACE_POKEUSER:
-+ result = ptrace(arg1, child, arg3, arg4);
-+ if(result == -1) return(-errno);
-+
-+ if(arg1 == PTRACE_POKEUSER) ptrace_pokeuser(arg3, arg4);
-+ return(result);
-+
-+#ifdef UM_HAVE_SETFPREGS
-+ case PTRACE_SETFPREGS:
-+ {
-+ long regs[FP_FRAME_SIZE];
-+ int i;
-+
-+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
-+ regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid,
-+ arg4 + 4 * i, 0);
-+ result = ptrace(PTRACE_SETFPREGS, child, 0, regs);
-+ if(result == -1) return(-errno);
-+
-+ return(result);
-+ }
-+#endif
-+
-+#ifdef UM_HAVE_SETFPXREGS
-+ case PTRACE_SETFPXREGS:
-+ {
-+ long regs[FPX_FRAME_SIZE];
-+ int i;
-+
-+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
-+ regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid,
-+ arg4 + 4 * i, 0);
-+ result = ptrace(PTRACE_SETFPXREGS, child, 0, regs);
-+ if(result == -1) return(-errno);
-+
-+ return(result);
-+ }
-+#endif
-+
-+#ifdef UM_HAVE_SETREGS
-+ case PTRACE_SETREGS:
-+ {
-+ long regs[FRAME_SIZE];
-+ int i;
-+
-+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
-+ regs[i] = ptrace(PTRACE_PEEKDATA, debugger->pid,
-+ arg4 + 4 * i, 0);
-+ result = ptrace(PTRACE_SETREGS, child, 0, regs);
-+ if(result == -1) return(-errno);
-+
-+ return(result);
-+ }
-+#endif
-+
-+ case PTRACE_SINGLESTEP:
-+ if(!debugger->debugee->in_context) return(-EPERM);
-+ sigemptyset(&relay);
-+ sigaddset(&relay, SIGSEGV);
-+ sigaddset(&relay, SIGILL);
-+ sigaddset(&relay, SIGBUS);
-+ result = ptrace(PTRACE_SINGLESTEP, child, arg3, arg4);
-+ if(result == -1) return(-errno);
-+
-+ status = wait_for_stop(child, SIGTRAP, PTRACE_SINGLESTEP,
-+ &relay);
-+ child_proxy(child, status);
-+ return(result);
-+
-+ case PTRACE_SYSCALL:
-+ if(!debugger->debugee->in_context) return(-EPERM);
-+ result = ptrace(PTRACE_SYSCALL, child, arg3, arg4);
-+ if(result == -1) return(-errno);
-+
-+ *ret = PTRACE_SYSCALL;
-+ return(result);
-+
-+ case PTRACE_TRACEME:
-+ default:
-+ return(-EINVAL);
-+ }
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/sysdep.c um/arch/um/kernel/tt/ptproxy/sysdep.c
---- orig/arch/um/kernel/tt/ptproxy/sysdep.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/ptproxy/sysdep.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,72 @@
-+/**********************************************************************
-+sysdep.c
-+
-+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
-+terms and conditions.
-+**********************************************************************/
-+
-+#include <stdio.h>
-+#include <string.h>
-+#include <stdlib.h>
-+#include <signal.h>
-+#include <errno.h>
-+#include <sys/types.h>
-+#include <sys/ptrace.h>
-+#include <asm/ptrace.h>
-+#include <linux/unistd.h>
-+#include "ptrace_user.h"
-+#include "user_util.h"
-+#include "user.h"
-+
-+int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4,
-+ long *arg5)
-+{
-+ *arg1 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG1_OFFSET, 0);
-+ *arg2 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG2_OFFSET, 0);
-+ *arg3 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG3_OFFSET, 0);
-+ *arg4 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG4_OFFSET, 0);
-+ *arg5 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG5_OFFSET, 0);
-+ return(ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET, 0));
-+}
-+
-+void syscall_cancel(pid_t pid, int result)
-+{
-+ if((ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
-+ __NR_getpid) < 0) ||
-+ (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) ||
-+ (wait_for_stop(pid, SIGTRAP, PTRACE_SYSCALL, NULL) < 0) ||
-+ (ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, result) < 0) ||
-+ (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0))
-+ printk("ptproxy: couldn't cancel syscall: errno = %d\n",
-+ errno);
-+}
-+
-+void syscall_set_result(pid_t pid, long result)
-+{
-+ ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, result);
-+}
-+
-+void syscall_continue(pid_t pid)
-+{
-+ ptrace(PTRACE_SYSCALL, pid, 0, 0);
-+}
-+
-+int syscall_pause(pid_t pid)
-+{
-+ if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_pause) < 0){
-+ printk("syscall_change - ptrace failed, errno = %d\n", errno);
-+ return(-1);
-+ }
-+ return(0);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/sysdep.h um/arch/um/kernel/tt/ptproxy/sysdep.h
---- orig/arch/um/kernel/tt/ptproxy/sysdep.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/ptproxy/sysdep.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,25 @@
-+/**********************************************************************
-+sysdep.h
-+
-+Copyright (C) 1999 Lars Brinkhoff.
-+Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
-+See the file COPYING for licensing terms and conditions.
-+**********************************************************************/
-+
-+extern int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3,
-+ long *arg4, long *arg5);
-+extern void syscall_cancel (pid_t pid, long result);
-+extern void syscall_set_result (pid_t pid, long result);
-+extern void syscall_continue (pid_t pid);
-+extern int syscall_pause(pid_t pid);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/wait.c um/arch/um/kernel/tt/ptproxy/wait.c
---- orig/arch/um/kernel/tt/ptproxy/wait.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/ptproxy/wait.c 2004-01-17 05:27:18.000000000 -0500
-@@ -0,0 +1,88 @@
-+/**********************************************************************
-+wait.c
-+
-+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
-+terms and conditions.
-+
-+**********************************************************************/
-+
-+#include <errno.h>
-+#include <signal.h>
-+#include <sys/wait.h>
-+#include <sys/ptrace.h>
-+#include <asm/ptrace.h>
-+
-+#include "ptproxy.h"
-+#include "sysdep.h"
-+#include "wait.h"
-+#include "user_util.h"
-+#include "sysdep/ptrace.h"
-+#include "sysdep/ptrace_user.h"
-+#include "sysdep/sigcontext.h"
-+
-+int proxy_wait_return(struct debugger *debugger, pid_t unused)
-+{
-+ debugger->waiting = 0;
-+
-+ if(debugger->debugee->died || (debugger->wait_options & __WCLONE)){
-+ debugger_cancelled_return(debugger, -ECHILD);
-+ return(0);
-+ }
-+
-+ if(debugger->debugee->zombie && debugger->debugee->event)
-+ debugger->debugee->died = 1;
-+
-+ if(debugger->debugee->event){
-+ debugger->debugee->event = 0;
-+ ptrace(PTRACE_POKEDATA, debugger->pid,
-+ debugger->wait_status_ptr,
-+ debugger->debugee->wait_status);
-+ /* if (wait4)
-+ ptrace (PTRACE_POKEDATA, pid, rusage_ptr, ...); */
-+ debugger_cancelled_return(debugger, debugger->debugee->pid);
-+ return(0);
-+ }
-+
-+ /* pause will return -EINTR, which happens to be right for wait */
-+ debugger_normal_return(debugger, -1);
-+ return(0);
-+}
-+
-+int parent_wait_return(struct debugger *debugger, pid_t unused)
-+{
-+ return(debugger_normal_return(debugger, -1));
-+}
-+
-+int real_wait_return(struct debugger *debugger)
-+{
-+ unsigned long ip;
-+ int pid;
-+
-+ pid = debugger->pid;
-+
-+ ip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0);
-+ IP_RESTART_SYSCALL(ip);
-+
-+ if(ptrace(PTRACE_POKEUSER, pid, PT_IP_OFFSET, ip) < 0)
-+ tracer_panic("real_wait_return : Failed to restart system "
-+ "call, errno = %d\n", errno);
-+
-+ if((ptrace(PTRACE_SYSCALL, debugger->pid, 0, SIGCHLD) < 0) ||
-+ (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) ||
-+ (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) ||
-+ debugger_normal_return(debugger, -1))
-+ tracer_panic("real_wait_return : gdb failed to wait, "
-+ "errno = %d\n", errno);
-+ return(0);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/wait.h um/arch/um/kernel/tt/ptproxy/wait.h
---- orig/arch/um/kernel/tt/ptproxy/wait.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/ptproxy/wait.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,15 @@
-+/**********************************************************************
-+wait.h
-+
-+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
-+terms and conditions.
-+**********************************************************************/
-+
-+#ifndef __PTPROXY_WAIT_H
-+#define __PTPROXY_WAIT_H
-+
-+extern int proxy_wait_return(struct debugger *debugger, pid_t unused);
-+extern int real_wait_return(struct debugger *debugger);
-+extern int parent_wait_return(struct debugger *debugger, pid_t unused);
-+
-+#endif
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/syscall_kern.c um/arch/um/kernel/tt/syscall_kern.c
---- orig/arch/um/kernel/tt/syscall_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/syscall_kern.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,142 @@
-+/*
-+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/types.h"
-+#include "linux/utime.h"
-+#include "linux/sys.h"
-+#include "asm/unistd.h"
-+#include "asm/ptrace.h"
-+#include "asm/uaccess.h"
-+#include "sysdep/syscalls.h"
-+#include "kern_util.h"
-+
-+static inline int check_area(void *ptr, int size)
-+{
-+ return(verify_area(VERIFY_WRITE, ptr, size));
-+}
-+
-+static int check_readlink(struct pt_regs *regs)
-+{
-+ return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs),
-+ UPT_SYSCALL_ARG2(®s->regs)));
-+}
-+
-+static int check_utime(struct pt_regs *regs)
-+{
-+ return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs),
-+ sizeof(struct utimbuf)));
-+}
-+
-+static int check_oldstat(struct pt_regs *regs)
-+{
-+ return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs),
-+ sizeof(struct __old_kernel_stat)));
-+}
-+
-+static int check_stat(struct pt_regs *regs)
-+{
-+ return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs),
-+ sizeof(struct stat)));
-+}
-+
-+static int check_stat64(struct pt_regs *regs)
-+{
-+ return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs),
-+ sizeof(struct stat64)));
-+}
-+
-+struct bogus {
-+ int kernel_ds;
-+ int (*check_params)(struct pt_regs *);
-+};
-+
-+struct bogus this_is_bogus[256] = {
-+ [ __NR_mknod ] = { 1, NULL },
-+ [ __NR_mkdir ] = { 1, NULL },
-+ [ __NR_rmdir ] = { 1, NULL },
-+ [ __NR_unlink ] = { 1, NULL },
-+ [ __NR_symlink ] = { 1, NULL },
-+ [ __NR_link ] = { 1, NULL },
-+ [ __NR_rename ] = { 1, NULL },
-+ [ __NR_umount ] = { 1, NULL },
-+ [ __NR_mount ] = { 1, NULL },
-+ [ __NR_pivot_root ] = { 1, NULL },
-+ [ __NR_chdir ] = { 1, NULL },
-+ [ __NR_chroot ] = { 1, NULL },
-+ [ __NR_open ] = { 1, NULL },
-+ [ __NR_quotactl ] = { 1, NULL },
-+ [ __NR_sysfs ] = { 1, NULL },
-+ [ __NR_readlink ] = { 1, check_readlink },
-+ [ __NR_acct ] = { 1, NULL },
-+ [ __NR_execve ] = { 1, NULL },
-+ [ __NR_uselib ] = { 1, NULL },
-+ [ __NR_statfs ] = { 1, NULL },
-+ [ __NR_truncate ] = { 1, NULL },
-+ [ __NR_access ] = { 1, NULL },
-+ [ __NR_chmod ] = { 1, NULL },
-+ [ __NR_chown ] = { 1, NULL },
-+ [ __NR_lchown ] = { 1, NULL },
-+ [ __NR_utime ] = { 1, check_utime },
-+ [ __NR_oldlstat ] = { 1, check_oldstat },
-+ [ __NR_oldstat ] = { 1, check_oldstat },
-+ [ __NR_stat ] = { 1, check_stat },
-+ [ __NR_lstat ] = { 1, check_stat },
-+ [ __NR_stat64 ] = { 1, check_stat64 },
-+ [ __NR_lstat64 ] = { 1, check_stat64 },
-+ [ __NR_chown32 ] = { 1, NULL },
-+};
-+
-+/* sys_utimes */
-+
-+static int check_bogosity(struct pt_regs *regs)
-+{
-+ struct bogus *bogon = &this_is_bogus[UPT_SYSCALL_NR(®s->regs)];
-+
-+ if(!bogon->kernel_ds) return(0);
-+ if(bogon->check_params && (*bogon->check_params)(regs))
-+ return(-EFAULT);
-+ set_fs(KERNEL_DS);
-+ return(0);
-+}
-+
-+extern syscall_handler_t *sys_call_table[];
-+
-+long execute_syscall_tt(void *r)
-+{
-+ struct pt_regs *regs = r;
-+ long res;
-+ int syscall;
-+
-+ current->thread.nsyscalls++;
-+ nsyscalls++;
-+ syscall = UPT_SYSCALL_NR(®s->regs);
-+
-+ if((syscall >= NR_syscalls) || (syscall < 0))
-+ res = -ENOSYS;
-+ else if(honeypot && check_bogosity(regs))
-+ res = -EFAULT;
-+ else res = EXECUTE_SYSCALL(syscall, regs);
-+
-+ set_fs(USER_DS);
-+
-+ if(current->thread.mode.tt.singlestep_syscall){
-+ current->thread.mode.tt.singlestep_syscall = 0;
-+ current->ptrace &= ~PT_DTRACE;
-+ force_sig(SIGTRAP, current);
-+ }
-+
-+ return(res);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/syscall_user.c um/arch/um/kernel/tt/syscall_user.c
---- orig/arch/um/kernel/tt/syscall_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/syscall_user.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,89 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <unistd.h>
-+#include <signal.h>
-+#include <errno.h>
-+#include <sys/ptrace.h>
-+#include <asm/unistd.h>
-+#include "sysdep/ptrace.h"
-+#include "sigcontext.h"
-+#include "ptrace_user.h"
-+#include "task.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "syscall_user.h"
-+#include "tt.h"
-+
-+/* XXX Bogus */
-+#define ERESTARTSYS 512
-+#define ERESTARTNOINTR 513
-+#define ERESTARTNOHAND 514
-+
-+void syscall_handler_tt(int sig, union uml_pt_regs *regs)
-+{
-+ void *sc;
-+ long result;
-+ int index, syscall;
-+
-+ syscall = UPT_SYSCALL_NR(regs);
-+ sc = UPT_SC(regs);
-+ SC_START_SYSCALL(sc);
-+
-+ index = record_syscall_start(syscall);
-+ syscall_trace();
-+ result = execute_syscall(regs);
-+
-+ /* regs->sc may have changed while the system call ran (there may
-+ * have been an interrupt or segfault), so it needs to be refreshed.
-+ */
-+ UPT_SC(regs) = sc;
-+
-+ SC_SET_SYSCALL_RETURN(sc, result);
-+ if((result == -ERESTARTNOHAND) || (result == -ERESTARTSYS) ||
-+ (result == -ERESTARTNOINTR))
-+ do_signal(result);
-+
-+ syscall_trace();
-+ record_syscall_end(index, result);
-+}
-+
-+int do_syscall(void *task, int pid)
-+{
-+ unsigned long proc_regs[FRAME_SIZE];
-+ union uml_pt_regs *regs;
-+ int syscall;
-+
-+ if(ptrace_getregs(pid, proc_regs) < 0)
-+ tracer_panic("Couldn't read registers");
-+ syscall = PT_SYSCALL_NR(proc_regs);
-+
-+ regs = TASK_REGS(task);
-+ UPT_SYSCALL_NR(regs) = syscall;
-+
-+ if(syscall < 1) return(0);
-+
-+ if((syscall != __NR_sigreturn) &&
-+ ((unsigned long *) PT_IP(proc_regs) >= &_stext) &&
-+ ((unsigned long *) PT_IP(proc_regs) <= &_etext))
-+ tracer_panic("I'm tracing myself and I can't get out");
-+
-+ if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
-+ __NR_getpid) < 0)
-+ tracer_panic("do_syscall : Nullifying syscall failed, "
-+ "errno = %d", errno);
-+ return(1);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/sys-i386/Makefile um/arch/um/kernel/tt/sys-i386/Makefile
---- orig/arch/um/kernel/tt/sys-i386/Makefile 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/sys-i386/Makefile 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,17 @@
-+#
-+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+# Licensed under the GPL
-+#
-+
-+O_TARGET = sys-i386.o
-+
-+obj-y = sigcontext.o
-+
-+USER_OBJS = sigcontext.o
-+
-+include $(TOPDIR)/Rules.make
-+
-+$(USER_OBJS) : %.o: %.c
-+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $<
-+
-+clean :
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/sys-i386/sigcontext.c um/arch/um/kernel/tt/sys-i386/sigcontext.c
---- orig/arch/um/kernel/tt/sys-i386/sigcontext.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/sys-i386/sigcontext.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,60 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdlib.h>
-+#include <asm/sigcontext.h>
-+#include "kern_util.h"
-+#include "sysdep/frame.h"
-+
-+int copy_sc_from_user_tt(void *to_ptr, void *from_ptr, void *data)
-+{
-+ struct arch_frame_data *arch = data;
-+ struct sigcontext *to = to_ptr, *from = from_ptr;
-+ struct _fpstate *to_fp, *from_fp;
-+ unsigned long sigs;
-+ int err;
-+
-+ to_fp = to->fpstate;
-+ from_fp = from->fpstate;
-+ sigs = to->oldmask;
-+ err = copy_from_user_proc(to, from, sizeof(*to));
-+ to->oldmask = sigs;
-+ if(to_fp != NULL){
-+ err |= copy_from_user_proc(&to->fpstate, &to_fp,
-+ sizeof(to->fpstate));
-+ err |= copy_from_user_proc(to_fp, from_fp, arch->fpstate_size);
-+ }
-+ return(err);
-+}
-+
-+int copy_sc_to_user_tt(void *to_ptr, void *fp, void *from_ptr, void *data)
-+{
-+ struct arch_frame_data *arch = data;
-+ struct sigcontext *to = to_ptr, *from = from_ptr;
-+ struct _fpstate *to_fp, *from_fp;
-+ int err;
-+
-+ to_fp = (struct _fpstate *)
-+ (fp ? (unsigned long) fp : ((unsigned long) to + sizeof(*to)));
-+ from_fp = from->fpstate;
-+ err = copy_to_user_proc(to, from, sizeof(*to));
-+ if(from_fp != NULL){
-+ err |= copy_to_user_proc(&to->fpstate, &to_fp,
-+ sizeof(to->fpstate));
-+ err |= copy_to_user_proc(to_fp, from_fp, arch->fpstate_size);
-+ }
-+ return(err);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/time.c um/arch/um/kernel/tt/time.c
---- orig/arch/um/kernel/tt/time.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/time.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,28 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <signal.h>
-+#include <sys/time.h>
-+#include <time_user.h>
-+#include "process.h"
-+#include "user.h"
-+
-+void user_time_init_tt(void)
-+{
-+ if(signal(SIGVTALRM, (__sighandler_t) alarm_handler) == SIG_ERR)
-+ panic("Couldn't set SIGVTALRM handler");
-+ set_interval(ITIMER_VIRTUAL);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/tlb.c um/arch/um/kernel/tt/tlb.c
---- orig/arch/um/kernel/tt/tlb.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/tlb.c 2003-11-13 00:40:57.000000000 -0500
-@@ -0,0 +1,220 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/stddef.h"
-+#include "linux/kernel.h"
-+#include "linux/sched.h"
-+#include "asm/page.h"
-+#include "asm/pgtable.h"
-+#include "asm/uaccess.h"
-+#include "user_util.h"
-+#include "mem_user.h"
-+#include "os.h"
-+
-+static void fix_range(struct mm_struct *mm, unsigned long start_addr,
-+ unsigned long end_addr, int force)
-+{
-+ pgd_t *npgd;
-+ pmd_t *npmd;
-+ pte_t *npte;
-+ unsigned long addr;
-+ int r, w, x, err;
-+
-+ if((current->thread.mode.tt.extern_pid != -1) &&
-+ (current->thread.mode.tt.extern_pid != os_getpid()))
-+ panic("fix_range fixing wrong address space, current = 0x%p",
-+ current);
-+ if(mm == NULL) return;
-+ for(addr=start_addr;addr<end_addr;){
-+ if(addr == TASK_SIZE){
-+ /* Skip over kernel text, kernel data, and physical
-+ * memory, which don't have ptes, plus kernel virtual
-+ * memory, which is flushed separately, and remap
-+ * the process stack. The only way to get here is
-+ * if (end_addr == STACK_TOP) > TASK_SIZE, which is
-+ * only true in the honeypot case.
-+ */
-+ addr = STACK_TOP - ABOVE_KMEM;
-+ continue;
-+ }
-+ npgd = pgd_offset(mm, addr);
-+ npmd = pmd_offset(npgd, addr);
-+ if(pmd_present(*npmd)){
-+ npte = pte_offset(npmd, addr);
-+ r = pte_read(*npte);
-+ w = pte_write(*npte);
-+ x = pte_exec(*npte);
-+ if(!pte_dirty(*npte)) w = 0;
-+ if(!pte_young(*npte)){
-+ r = 0;
-+ w = 0;
-+ }
-+ if(force || pte_newpage(*npte)){
-+ err = os_unmap_memory((void *) addr,
-+ PAGE_SIZE);
-+ if(err < 0)
-+ panic("munmap failed, errno = %d\n",
-+ -err);
-+ if(pte_present(*npte))
-+ map_memory(addr,
-+ pte_val(*npte) & PAGE_MASK,
-+ PAGE_SIZE, r, w, x);
-+ }
-+ else if(pte_newprot(*npte)){
-+ protect_memory(addr, PAGE_SIZE, r, w, x, 1);
-+ }
-+ *npte = pte_mkuptodate(*npte);
-+ addr += PAGE_SIZE;
-+ }
-+ else {
-+ if(force || pmd_newpage(*npmd)){
-+ err = os_unmap_memory((void *) addr, PMD_SIZE);
-+ if(err < 0)
-+ panic("munmap failed, errno = %d\n",
-+ -err);
-+ pmd_mkuptodate(*npmd);
-+ }
-+ addr += PMD_SIZE;
-+ }
-+ }
-+}
-+
-+atomic_t vmchange_seq = ATOMIC_INIT(1);
-+
-+static void flush_kernel_vm_range(unsigned long start, unsigned long end,
-+ int update_seq)
-+{
-+ struct mm_struct *mm;
-+ pgd_t *pgd;
-+ pmd_t *pmd;
-+ pte_t *pte;
-+ unsigned long addr;
-+ int updated = 0, err;
-+
-+ mm = &init_mm;
-+ for(addr = start; addr < end;){
-+ pgd = pgd_offset(mm, addr);
-+ pmd = pmd_offset(pgd, addr);
-+ if(pmd_present(*pmd)){
-+ pte = pte_offset(pmd, addr);
-+ if(!pte_present(*pte) || pte_newpage(*pte)){
-+ updated = 1;
-+ err = os_unmap_memory((void *) addr,
-+ PAGE_SIZE);
-+ if(err < 0)
-+ panic("munmap failed, errno = %d\n",
-+ -err);
-+ if(pte_present(*pte))
-+ map_memory(addr,
-+ pte_val(*pte) & PAGE_MASK,
-+ PAGE_SIZE, 1, 1, 1);
-+ }
-+ else if(pte_newprot(*pte)){
-+ updated = 1;
-+ protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1);
-+ }
-+ addr += PAGE_SIZE;
-+ }
-+ else {
-+ if(pmd_newpage(*pmd)){
-+ updated = 1;
-+ err = os_unmap_memory((void *) addr, PMD_SIZE);
-+ if(err < 0)
-+ panic("munmap failed, errno = %d\n",
-+ -err);
-+ }
-+ addr += PMD_SIZE;
-+ }
-+ }
-+ if(updated && update_seq) atomic_inc(&vmchange_seq);
-+}
-+
-+static void protect_vm_page(unsigned long addr, int w, int must_succeed)
-+{
-+ int err;
-+
-+ err = protect_memory(addr, PAGE_SIZE, 1, w, 1, must_succeed);
-+ if(err == 0) return;
-+ else if((err == -EFAULT) || (err == -ENOMEM)){
-+ flush_kernel_vm_range(addr, addr + PAGE_SIZE, 1);
-+ protect_vm_page(addr, w, 1);
-+ }
-+ else panic("protect_vm_page : protect failed, errno = %d\n", err);
-+}
-+
-+void mprotect_kernel_vm(int w)
-+{
-+ struct mm_struct *mm;
-+ pgd_t *pgd;
-+ pmd_t *pmd;
-+ pte_t *pte;
-+ unsigned long addr;
-+
-+ mm = &init_mm;
-+ for(addr = start_vm; addr < end_vm;){
-+ pgd = pgd_offset(mm, addr);
-+ pmd = pmd_offset(pgd, addr);
-+ if(pmd_present(*pmd)){
-+ pte = pte_offset(pmd, addr);
-+ if(pte_present(*pte)) protect_vm_page(addr, w, 0);
-+ addr += PAGE_SIZE;
-+ }
-+ else addr += PMD_SIZE;
-+ }
-+}
-+
-+void flush_tlb_kernel_vm_tt(void)
-+{
-+ flush_kernel_vm_range(start_vm, end_vm, 1);
-+}
-+
-+void __flush_tlb_one_tt(unsigned long addr)
-+{
-+ flush_kernel_vm_range(addr, addr + PAGE_SIZE, 1);
-+}
-+
-+void flush_tlb_range_tt(struct mm_struct *mm, unsigned long start,
-+ unsigned long end)
-+{
-+ if(mm != current->mm) return;
-+
-+ /* Assumes that the range start ... end is entirely within
-+ * either process memory or kernel vm
-+ */
-+ if((start >= start_vm) && (start < end_vm))
-+ flush_kernel_vm_range(start, end, 1);
-+ else fix_range(mm, start, end, 0);
-+}
-+
-+void flush_tlb_mm_tt(struct mm_struct *mm)
-+{
-+ unsigned long seq;
-+
-+ if(mm != current->mm) return;
-+
-+ fix_range(mm, 0, STACK_TOP, 0);
-+
-+ seq = atomic_read(&vmchange_seq);
-+ if(current->thread.mode.tt.vm_seq == seq) return;
-+ current->thread.mode.tt.vm_seq = seq;
-+ flush_kernel_vm_range(start_vm, end_vm, 0);
-+}
-+
-+void force_flush_all_tt(void)
-+{
-+ fix_range(current->mm, 0, STACK_TOP, 1);
-+ flush_kernel_vm_range(start_vm, end_vm, 0);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/tracer.c um/arch/um/kernel/tt/tracer.c
---- orig/arch/um/kernel/tt/tracer.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/tracer.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,454 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <stdarg.h>
-+#include <unistd.h>
-+#include <signal.h>
-+#include <errno.h>
-+#include <sched.h>
-+#include <string.h>
-+#include <sys/mman.h>
-+#include <sys/ptrace.h>
-+#include <sys/time.h>
-+#include <sys/wait.h>
-+#include "user.h"
-+#include "sysdep/ptrace.h"
-+#include "sigcontext.h"
-+#include "sysdep/sigcontext.h"
-+#include "os.h"
-+#include "signal_user.h"
-+#include "user_util.h"
-+#include "mem_user.h"
-+#include "process.h"
-+#include "kern_util.h"
-+#include "frame.h"
-+#include "chan_user.h"
-+#include "ptrace_user.h"
-+#include "mode.h"
-+#include "tt.h"
-+
-+static int tracer_winch[2];
-+
-+int is_tracer_winch(int pid, int fd, void *data)
-+{
-+ if(pid != tracing_pid)
-+ return(0);
-+
-+ register_winch_irq(tracer_winch[0], fd, -1, data);
-+ return(1);
-+}
-+
-+static void tracer_winch_handler(int sig)
-+{
-+ int n;
-+ char c = 1;
-+
-+ n = os_write_file(tracer_winch[1], &c, sizeof(c));
-+ if(n != sizeof(c))
-+ printk("tracer_winch_handler - write failed, err = %d\n", -n);
-+}
-+
-+/* Called only by the tracing thread during initialization */
-+
-+static void setup_tracer_winch(void)
-+{
-+ int err;
-+
-+ err = os_pipe(tracer_winch, 1, 1);
-+ if(err < 0){
-+ printk("setup_tracer_winch : os_pipe failed, err = %d\n", -err);
-+ return;
-+ }
-+ signal(SIGWINCH, tracer_winch_handler);
-+}
-+
-+void attach_process(int pid)
-+{
-+ if((ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) ||
-+ (ptrace(PTRACE_CONT, pid, 0, 0) < 0))
-+ tracer_panic("OP_FORK failed to attach pid");
-+ wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL);
-+ if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
-+ tracer_panic("OP_FORK failed to continue process");
-+}
-+
-+void tracer_panic(char *format, ...)
-+{
-+ va_list ap;
-+
-+ va_start(ap, format);
-+ vprintf(format, ap);
-+ printf("\n");
-+ while(1) pause();
-+}
-+
-+static void tracer_segv(int sig, struct sigcontext sc)
-+{
-+ printf("Tracing thread segfault at address 0x%lx, ip 0x%lx\n",
-+ SC_FAULT_ADDR(&sc), SC_IP(&sc));
-+ while(1)
-+ pause();
-+}
-+
-+/* Changed early in boot, and then only read */
-+int debug = 0;
-+int debug_stop = 1;
-+int debug_parent = 0;
-+int honeypot = 0;
-+
-+static int signal_tramp(void *arg)
-+{
-+ int (*proc)(void *);
-+
-+ if(honeypot && munmap((void *) (host_task_size - 0x10000000),
-+ 0x10000000))
-+ panic("Unmapping stack failed");
-+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
-+ panic("ptrace PTRACE_TRACEME failed");
-+ os_stop_process(os_getpid());
-+ change_sig(SIGWINCH, 0);
-+ signal(SIGUSR1, SIG_IGN);
-+ change_sig(SIGCHLD, 0);
-+ signal(SIGSEGV, (__sighandler_t) sig_handler);
-+ set_cmdline("(idle thread)");
-+ set_init_pid(os_getpid());
-+ proc = arg;
-+ return((*proc)(NULL));
-+}
-+
-+static void sleeping_process_signal(int pid, int sig)
-+{
-+ switch(sig){
-+ /* These two result from UML being ^Z-ed and bg-ed. PTRACE_CONT is
-+ * right because the process must be in the kernel already.
-+ */
-+ case SIGCONT:
-+ case SIGTSTP:
-+ if(ptrace(PTRACE_CONT, pid, 0, sig) < 0)
-+ tracer_panic("sleeping_process_signal : Failed to "
-+ "continue pid %d, signal = %d, "
-+ "errno = %d\n", pid, sig, errno);
-+ break;
-+
-+ /* This happens when the debugger (e.g. strace) is doing system call
-+ * tracing on the kernel. During a context switch, the current task
-+ * will be set to the incoming process and the outgoing process will
-+ * hop into write and then read. Since it's not the current process
-+ * any more, the trace of those will land here. So, we need to just
-+ * PTRACE_SYSCALL it.
-+ */
-+ case SIGTRAP:
-+ if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
-+ tracer_panic("sleeping_process_signal : Failed to "
-+ "PTRACE_SYSCALL pid %d, errno = %d\n",
-+ pid, errno);
-+ break;
-+ case SIGSTOP:
-+ break;
-+ default:
-+ tracer_panic("sleeping process %d got unexpected "
-+ "signal : %d\n", pid, sig);
-+ break;
-+ }
-+}
-+
-+/* Accessed only by the tracing thread */
-+int debugger_pid = -1;
-+int debugger_parent = -1;
-+int debugger_fd = -1;
-+int gdb_pid = -1;
-+
-+struct {
-+ int pid;
-+ int signal;
-+ unsigned long addr;
-+ struct timeval time;
-+} signal_record[1024][32];
-+
-+int signal_index[32];
-+int nsignals = 0;
-+int debug_trace = 0;
-+extern int io_nsignals, io_count, intr_count;
-+
-+extern void signal_usr1(int sig);
-+
-+int tracing_pid = -1;
-+
-+int tracer(int (*init_proc)(void *), void *sp)
-+{
-+ void *task = NULL;
-+ unsigned long eip = 0;
-+ int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0;
-+ int last_index, proc_id = 0, n, err, old_tracing = 0, strace = 0;
-+
-+ capture_signal_stack();
-+ signal(SIGPIPE, SIG_IGN);
-+ setup_tracer_winch();
-+ tracing_pid = os_getpid();
-+ printf("tracing thread pid = %d\n", tracing_pid);
-+
-+ pid = clone(signal_tramp, sp, CLONE_FILES | SIGCHLD, init_proc);
-+ n = waitpid(pid, &status, WUNTRACED);
-+ if(n < 0){
-+ printf("waitpid on idle thread failed, errno = %d\n", errno);
-+ exit(1);
-+ }
-+ if((ptrace(PTRACE_CONT, pid, 0, 0) < 0)){
-+ printf("Failed to continue idle thread, errno = %d\n", errno);
-+ exit(1);
-+ }
-+
-+ signal(SIGSEGV, (sighandler_t) tracer_segv);
-+ signal(SIGUSR1, signal_usr1);
-+ if(debug_trace){
-+ printf("Tracing thread pausing to be attached\n");
-+ stop();
-+ }
-+ if(debug){
-+ if(gdb_pid != -1)
-+ debugger_pid = attach_debugger(pid, gdb_pid, 1);
-+ else debugger_pid = init_ptrace_proxy(pid, 1, debug_stop);
-+ if(debug_parent){
-+ debugger_parent = os_process_parent(debugger_pid);
-+ init_parent_proxy(debugger_parent);
-+ err = attach(debugger_parent);
-+ if(err){
-+ printf("Failed to attach debugger parent %d, "
-+ "errno = %d\n", debugger_parent, -err);
-+ debugger_parent = -1;
-+ }
-+ else {
-+ if(ptrace(PTRACE_SYSCALL, debugger_parent,
-+ 0, 0) < 0){
-+ printf("Failed to continue debugger "
-+ "parent, errno = %d\n", errno);
-+ debugger_parent = -1;
-+ }
-+ }
-+ }
-+ }
-+ set_cmdline("(tracing thread)");
-+ while(1){
-+ pid = waitpid(-1, &status, WUNTRACED);
-+ if(pid <= 0){
-+ if(errno != ECHILD){
-+ printf("wait failed - errno = %d\n", errno);
-+ }
-+ continue;
-+ }
-+ if(pid == debugger_pid){
-+ int cont = 0;
-+
-+ if(WIFEXITED(status) || WIFSIGNALED(status))
-+ debugger_pid = -1;
-+ /* XXX Figure out how to deal with gdb and SMP */
-+ else cont = debugger_signal(status, cpu_tasks[0].pid);
-+ if(cont == PTRACE_SYSCALL) strace = 1;
-+ continue;
-+ }
-+ else if(pid == debugger_parent){
-+ debugger_parent_signal(status, pid);
-+ continue;
-+ }
-+ nsignals++;
-+ if(WIFEXITED(status)) ;
-+#ifdef notdef
-+ {
-+ printf("Child %d exited with status %d\n", pid,
-+ WEXITSTATUS(status));
-+ }
-+#endif
-+ else if(WIFSIGNALED(status)){
-+ sig = WTERMSIG(status);
-+ if(sig != 9){
-+ printf("Child %d exited with signal %d\n", pid,
-+ sig);
-+ }
-+ }
-+ else if(WIFSTOPPED(status)){
-+ proc_id = pid_to_processor_id(pid);
-+ sig = WSTOPSIG(status);
-+ if(signal_index[proc_id] == 1024){
-+ signal_index[proc_id] = 0;
-+ last_index = 1023;
-+ }
-+ else last_index = signal_index[proc_id] - 1;
-+ if(((sig == SIGPROF) || (sig == SIGVTALRM) ||
-+ (sig == SIGALRM)) &&
-+ (signal_record[proc_id][last_index].signal == sig)&&
-+ (signal_record[proc_id][last_index].pid == pid))
-+ signal_index[proc_id] = last_index;
-+ signal_record[proc_id][signal_index[proc_id]].pid = pid;
-+ gettimeofday(&signal_record[proc_id][signal_index[proc_id]].time, NULL);
-+ eip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0);
-+ signal_record[proc_id][signal_index[proc_id]].addr = eip;
-+ signal_record[proc_id][signal_index[proc_id]++].signal = sig;
-+
-+ if(proc_id == -1){
-+ sleeping_process_signal(pid, sig);
-+ continue;
-+ }
-+
-+ task = cpu_tasks[proc_id].task;
-+ tracing = is_tracing(task);
-+ old_tracing = tracing;
-+
-+ switch(sig){
-+ case SIGUSR1:
-+ sig = 0;
-+ op = do_proc_op(task, proc_id);
-+ switch(op){
-+ case OP_TRACE_ON:
-+ arch_leave_kernel(task, pid);
-+ tracing = 1;
-+ break;
-+ case OP_REBOOT:
-+ case OP_HALT:
-+ unmap_physmem();
-+ kmalloc_ok = 0;
-+ ptrace(PTRACE_KILL, pid, 0, 0);
-+ return(op == OP_REBOOT);
-+ case OP_NONE:
-+ printf("Detaching pid %d\n", pid);
-+ detach(pid, SIGSTOP);
-+ continue;
-+ default:
-+ break;
-+ }
-+ /* OP_EXEC switches host processes on us,
-+ * we want to continue the new one.
-+ */
-+ pid = cpu_tasks[proc_id].pid;
-+ break;
-+ case SIGTRAP:
-+ if(!tracing && (debugger_pid != -1)){
-+ child_signal(pid, status);
-+ continue;
-+ }
-+ tracing = 0;
-+ if(do_syscall(task, pid)) sig = SIGUSR2;
-+ else clear_singlestep(task);
-+ break;
-+ case SIGPROF:
-+ if(tracing) sig = 0;
-+ break;
-+ case SIGCHLD:
-+ case SIGHUP:
-+ sig = 0;
-+ break;
-+ case SIGSEGV:
-+ case SIGIO:
-+ case SIGALRM:
-+ case SIGVTALRM:
-+ case SIGFPE:
-+ case SIGBUS:
-+ case SIGILL:
-+ case SIGWINCH:
-+ default:
-+ tracing = 0;
-+ break;
-+ }
-+ set_tracing(task, tracing);
-+
-+ if(!tracing && old_tracing)
-+ arch_enter_kernel(task, pid);
-+
-+ if(!tracing && (debugger_pid != -1) && (sig != 0) &&
-+ (sig != SIGALRM) && (sig != SIGVTALRM) &&
-+ (sig != SIGSEGV) && (sig != SIGTRAP) &&
-+ (sig != SIGUSR2) && (sig != SIGIO) &&
-+ (sig != SIGFPE)){
-+ child_signal(pid, status);
-+ continue;
-+ }
-+
-+ if(tracing){
-+ if(singlestepping_tt(task))
-+ cont_type = PTRACE_SINGLESTEP;
-+ else cont_type = PTRACE_SYSCALL;
-+ }
-+ else cont_type = PTRACE_CONT;
-+
-+ if((cont_type == PTRACE_CONT) &&
-+ (debugger_pid != -1) && strace)
-+ cont_type = PTRACE_SYSCALL;
-+
-+ if(ptrace(cont_type, pid, 0, sig) != 0){
-+ tracer_panic("ptrace failed to continue "
-+ "process - errno = %d\n",
-+ errno);
-+ }
-+ }
-+ }
-+ return(0);
-+}
-+
-+static int __init uml_debug_setup(char *line, int *add)
-+{
-+ char *next;
-+
-+ debug = 1;
-+ *add = 0;
-+ if(*line != '=') return(0);
-+ line++;
-+
-+ while(line != NULL){
-+ next = strchr(line, ',');
-+ if(next) *next++ = '\0';
-+
-+ if(!strcmp(line, "go")) debug_stop = 0;
-+ else if(!strcmp(line, "parent")) debug_parent = 1;
-+ else printf("Unknown debug option : '%s'\n", line);
-+
-+ line = next;
-+ }
-+ return(0);
-+}
-+
-+__uml_setup("debug", uml_debug_setup,
-+"debug\n"
-+" Starts up the kernel under the control of gdb. See the \n"
-+" kernel debugging tutorial and the debugging session pages\n"
-+" at http://user-mode-linux.sourceforge.net/ for more information.\n\n"
-+);
-+
-+static int __init uml_debugtrace_setup(char *line, int *add)
-+{
-+ debug_trace = 1;
-+ return 0;
-+}
-+__uml_setup("debugtrace", uml_debugtrace_setup,
-+"debugtrace\n"
-+" Causes the tracing thread to pause until it is attached by a\n"
-+" debugger and continued. This is mostly for debugging crashes\n"
-+" early during boot, and should be pretty much obsoleted by\n"
-+" the debug switch.\n\n"
-+);
-+
-+static int __init uml_honeypot_setup(char *line, int *add)
-+{
-+ jail_setup("", add);
-+ honeypot = 1;
-+ return 0;
-+}
-+__uml_setup("honeypot", uml_honeypot_setup,
-+"honeypot\n"
-+" This makes UML put process stacks in the same location as they are\n"
-+" on the host, allowing expoits such as stack smashes to work against\n"
-+" UML. This implies 'jail'.\n\n"
-+);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/trap_user.c um/arch/um/kernel/tt/trap_user.c
---- orig/arch/um/kernel/tt/trap_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/trap_user.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,59 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdlib.h>
-+#include <errno.h>
-+#include <signal.h>
-+#include <asm/sigcontext.h>
-+#include "sysdep/ptrace.h"
-+#include "signal_user.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "task.h"
-+#include "tt.h"
-+
-+void sig_handler_common_tt(int sig, void *sc_ptr)
-+{
-+ struct sigcontext *sc = sc_ptr;
-+ struct tt_regs save_regs, *r;
-+ struct signal_info *info;
-+ int save_errno = errno, is_user;
-+
-+ unprotect_kernel_mem();
-+
-+ r = &TASK_REGS(get_current())->tt;
-+ save_regs = *r;
-+ is_user = user_context(SC_SP(sc));
-+ r->sc = sc;
-+ if(sig != SIGUSR2)
-+ r->syscall = -1;
-+
-+ change_sig(SIGUSR1, 1);
-+ info = &sig_info[sig];
-+ if(!info->is_irq) unblock_signals();
-+
-+ (*info->handler)(sig, (union uml_pt_regs *) r);
-+
-+ if(is_user){
-+ interrupt_end();
-+ block_signals();
-+ change_sig(SIGUSR1, 0);
-+ set_user_mode(NULL);
-+ }
-+ *r = save_regs;
-+ errno = save_errno;
-+ if(is_user) protect_kernel_mem();
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/uaccess.c um/arch/um/kernel/tt/uaccess.c
---- orig/arch/um/kernel/tt/uaccess.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/uaccess.c 2003-11-13 00:12:45.000000000 -0500
-@@ -0,0 +1,73 @@
-+/*
-+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/sched.h"
-+#include "asm/uaccess.h"
-+
-+int copy_from_user_tt(void *to, const void *from, int n)
-+{
-+ if(!access_ok_tt(VERIFY_READ, from, n))
-+ return(n);
-+
-+ return(__do_copy_from_user(to, from, n, ¤t->thread.fault_addr,
-+ ¤t->thread.fault_catcher));
-+}
-+
-+int copy_to_user_tt(void *to, const void *from, int n)
-+{
-+ if(!access_ok_tt(VERIFY_WRITE, to, n))
-+ return(n);
-+
-+ return(__do_copy_to_user(to, from, n, ¤t->thread.fault_addr,
-+ ¤t->thread.fault_catcher));
-+}
-+
-+int strncpy_from_user_tt(char *dst, const char *src, int count)
-+{
-+ int n;
-+
-+ if(!access_ok_tt(VERIFY_READ, src, 1))
-+ return(-EFAULT);
-+
-+ n = __do_strncpy_from_user(dst, src, count,
-+ ¤t->thread.fault_addr,
-+ ¤t->thread.fault_catcher);
-+ if(n < 0) return(-EFAULT);
-+ return(n);
-+}
-+
-+int __clear_user_tt(void *mem, int len)
-+{
-+ return(__do_clear_user(mem, len,
-+ ¤t->thread.fault_addr,
-+ ¤t->thread.fault_catcher));
-+}
-+
-+int clear_user_tt(void *mem, int len)
-+{
-+ if(!access_ok_tt(VERIFY_WRITE, mem, len))
-+ return(len);
-+
-+ return(__do_clear_user(mem, len, ¤t->thread.fault_addr,
-+ ¤t->thread.fault_catcher));
-+}
-+
-+int strnlen_user_tt(const void *str, int len)
-+{
-+ return(__do_strnlen_user(str, len,
-+ ¤t->thread.fault_addr,
-+ ¤t->thread.fault_catcher));
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/uaccess_user.c um/arch/um/kernel/tt/uaccess_user.c
---- orig/arch/um/kernel/tt/uaccess_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/uaccess_user.c 2004-01-31 02:48:29.000000000 -0500
-@@ -0,0 +1,98 @@
-+/*
-+ * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
-+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <setjmp.h>
-+#include <string.h>
-+#include "user_util.h"
-+#include "uml_uaccess.h"
-+#include "task.h"
-+#include "kern_util.h"
-+
-+int __do_copy_from_user(void *to, const void *from, int n,
-+ void **fault_addr, void **fault_catcher)
-+{
-+ struct tt_regs save = TASK_REGS(get_current())->tt;
-+ unsigned long fault;
-+ int faulted;
-+
-+ fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
-+ __do_copy, &faulted);
-+ TASK_REGS(get_current())->tt = save;
-+
-+ if(!faulted) return(0);
-+ else return(n - (fault - (unsigned long) from));
-+}
-+
-+static void __do_strncpy(void *dst, const void *src, int count)
-+{
-+ strncpy(dst, src, count);
-+}
-+
-+int __do_strncpy_from_user(char *dst, const char *src, unsigned long count,
-+ void **fault_addr, void **fault_catcher)
-+{
-+ struct tt_regs save = TASK_REGS(get_current())->tt;
-+ unsigned long fault;
-+ int faulted;
-+
-+ fault = __do_user_copy(dst, src, count, fault_addr, fault_catcher,
-+ __do_strncpy, &faulted);
-+ TASK_REGS(get_current())->tt = save;
-+
-+ if(!faulted) return(strlen(dst));
-+ else return(-1);
-+}
-+
-+static void __do_clear(void *to, const void *from, int n)
-+{
-+ memset(to, 0, n);
-+}
-+
-+int __do_clear_user(void *mem, unsigned long len,
-+ void **fault_addr, void **fault_catcher)
-+{
-+ struct tt_regs save = TASK_REGS(get_current())->tt;
-+ unsigned long fault;
-+ int faulted;
-+
-+ fault = __do_user_copy(mem, NULL, len, fault_addr, fault_catcher,
-+ __do_clear, &faulted);
-+ TASK_REGS(get_current())->tt = save;
-+
-+ if(!faulted) return(0);
-+ else return(len - (fault - (unsigned long) mem));
-+}
-+
-+int __do_strnlen_user(const char *str, unsigned long n,
-+ void **fault_addr, void **fault_catcher)
-+{
-+ struct tt_regs save = TASK_REGS(get_current())->tt;
-+ int ret;
-+ unsigned long *faddrp = (unsigned long *)fault_addr;
-+ sigjmp_buf jbuf;
-+
-+ *fault_catcher = &jbuf;
-+ if(sigsetjmp(jbuf, 1) == 0)
-+ ret = strlen(str) + 1;
-+ else ret = *faddrp - (unsigned long) str;
-+
-+ *fault_addr = NULL;
-+ *fault_catcher = NULL;
-+
-+ TASK_REGS(get_current())->tt = save;
-+ return ret;
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/unmap.c um/arch/um/kernel/tt/unmap.c
---- orig/arch/um/kernel/tt/unmap.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tt/unmap.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,31 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <sys/mman.h>
-+
-+int switcheroo(int fd, int prot, void *from, void *to, int size)
-+{
-+ if(munmap(to, size) < 0){
-+ return(-1);
-+ }
-+ if(mmap(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) != to){
-+ return(-1);
-+ }
-+ if(munmap(from, size) < 0){
-+ return(-1);
-+ }
-+ return(0);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/tty_log.c um/arch/um/kernel/tty_log.c
---- orig/arch/um/kernel/tty_log.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/tty_log.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,228 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) and
-+ * geoffrey hing <ghing@net.ohio-state.edu>
-+ * Licensed under the GPL
-+ */
-+
-+#include <errno.h>
-+#include <string.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <sys/time.h>
-+#include "init.h"
-+#include "user.h"
-+#include "kern_util.h"
-+#include "os.h"
-+
-+#define TTY_LOG_DIR "./"
-+
-+/* Set early in boot and then unchanged */
-+static char *tty_log_dir = TTY_LOG_DIR;
-+static int tty_log_fd = -1;
-+
-+#define TTY_LOG_OPEN 1
-+#define TTY_LOG_CLOSE 2
-+#define TTY_LOG_WRITE 3
-+#define TTY_LOG_EXEC 4
-+
-+#define TTY_READ 1
-+#define TTY_WRITE 2
-+
-+struct tty_log_buf {
-+ int what;
-+ unsigned long tty;
-+ int len;
-+ int direction;
-+ unsigned long sec;
-+ unsigned long usec;
-+};
-+
-+int open_tty_log(void *tty, void *current_tty)
-+{
-+ struct timeval tv;
-+ struct tty_log_buf data;
-+ char buf[strlen(tty_log_dir) + sizeof("01234567890-01234567\0")];
-+ int fd;
-+
-+ gettimeofday(&tv, NULL);
-+ if(tty_log_fd != -1){
-+ data = ((struct tty_log_buf) { .what = TTY_LOG_OPEN,
-+ .tty = (unsigned long) tty,
-+ .len = sizeof(current_tty),
-+ .direction = 0,
-+ .sec = tv.tv_sec,
-+ .usec = tv.tv_usec } );
-+ os_write_file(tty_log_fd, &data, sizeof(data));
-+ os_write_file(tty_log_fd, ¤t_tty, data.len);
-+ return(tty_log_fd);
-+ }
-+
-+ sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec,
-+ (unsigned int) tv.tv_usec);
-+
-+ fd = os_open_file(buf, of_append(of_create(of_rdwr(OPENFLAGS()))),
-+ 0644);
-+ if(fd < 0){
-+ printk("open_tty_log : couldn't open '%s', errno = %d\n",
-+ buf, -fd);
-+ }
-+ return(fd);
-+}
-+
-+void close_tty_log(int fd, void *tty)
-+{
-+ struct tty_log_buf data;
-+ struct timeval tv;
-+
-+ if(tty_log_fd != -1){
-+ gettimeofday(&tv, NULL);
-+ data = ((struct tty_log_buf) { .what = TTY_LOG_CLOSE,
-+ .tty = (unsigned long) tty,
-+ .len = 0,
-+ .direction = 0,
-+ .sec = tv.tv_sec,
-+ .usec = tv.tv_usec } );
-+ os_write_file(tty_log_fd, &data, sizeof(data));
-+ return;
-+ }
-+ os_close_file(fd);
-+}
-+
-+static int log_chunk(int fd, const char *buf, int len)
-+{
-+ int total = 0, try, missed, n;
-+ char chunk[64];
-+
-+ while(len > 0){
-+ try = (len > sizeof(chunk)) ? sizeof(chunk) : len;
-+ missed = copy_from_user_proc(chunk, (char *) buf, try);
-+ try -= missed;
-+ n = os_write_file(fd, chunk, try);
-+ if(n != try) {
-+ if(n < 0)
-+ return(n);
-+ return(-EIO);
-+ }
-+ if(missed != 0)
-+ return(-EFAULT);
-+
-+ len -= try;
-+ total += try;
-+ buf += try;
-+ }
-+
-+ return(total);
-+}
-+
-+int write_tty_log(int fd, const char *buf, int len, void *tty, int is_read)
-+{
-+ struct timeval tv;
-+ struct tty_log_buf data;
-+ int direction;
-+
-+ if(fd == tty_log_fd){
-+ gettimeofday(&tv, NULL);
-+ direction = is_read ? TTY_READ : TTY_WRITE;
-+ data = ((struct tty_log_buf) { .what = TTY_LOG_WRITE,
-+ .tty = (unsigned long) tty,
-+ .len = len,
-+ .direction = direction,
-+ .sec = tv.tv_sec,
-+ .usec = tv.tv_usec } );
-+ os_write_file(tty_log_fd, &data, sizeof(data));
-+ }
-+
-+ return(log_chunk(fd, buf, len));
-+}
-+
-+void log_exec(char **argv, void *tty)
-+{
-+ struct timeval tv;
-+ struct tty_log_buf data;
-+ char **ptr,*arg;
-+ int len;
-+
-+ if(tty_log_fd == -1) return;
-+
-+ gettimeofday(&tv, NULL);
-+
-+ len = 0;
-+ for(ptr = argv; ; ptr++){
-+ if(copy_from_user_proc(&arg, ptr, sizeof(arg)))
-+ return;
-+ if(arg == NULL) break;
-+ len += strlen_user_proc(arg);
-+ }
-+
-+ data = ((struct tty_log_buf) { .what = TTY_LOG_EXEC,
-+ .tty = (unsigned long) tty,
-+ .len = len,
-+ .direction = 0,
-+ .sec = tv.tv_sec,
-+ .usec = tv.tv_usec } );
-+ os_write_file(tty_log_fd, &data, sizeof(data));
-+
-+ for(ptr = argv; ; ptr++){
-+ if(copy_from_user_proc(&arg, ptr, sizeof(arg)))
-+ return;
-+ if(arg == NULL) break;
-+ log_chunk(tty_log_fd, arg, strlen_user_proc(arg));
-+ }
-+}
-+
-+extern void register_tty_logger(int (*opener)(void *, void *),
-+ int (*writer)(int, const char *, int,
-+ void *, int),
-+ void (*closer)(int, void *));
-+
-+static int register_logger(void)
-+{
-+ register_tty_logger(open_tty_log, write_tty_log, close_tty_log);
-+ return(0);
-+}
-+
-+__uml_initcall(register_logger);
-+
-+static int __init set_tty_log_dir(char *name, int *add)
-+{
-+ tty_log_dir = name;
-+ return 0;
-+}
-+
-+__uml_setup("tty_log_dir=", set_tty_log_dir,
-+"tty_log_dir=<directory>\n"
-+" This is used to specify the directory where the logs of all pty\n"
-+" data from this UML machine will be written.\n\n"
-+);
-+
-+static int __init set_tty_log_fd(char *name, int *add)
-+{
-+ char *end;
-+
-+ tty_log_fd = strtoul(name, &end, 0);
-+ if((*end != '\0') || (end == name)){
-+ printf("set_tty_log_fd - strtoul failed on '%s'\n", name);
-+ tty_log_fd = -1;
-+ }
-+ return 0;
-+}
-+
-+__uml_setup("tty_log_fd=", set_tty_log_fd,
-+"tty_log_fd=<fd>\n"
-+" This is used to specify a preconfigured file descriptor to which all\n"
-+" tty data will be written. Preconfigure the descriptor with something\n"
-+" like '10>tty_log tty_log_fd=10'.\n\n"
-+);
-+
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/uaccess_user.c um/arch/um/kernel/uaccess_user.c
---- orig/arch/um/kernel/uaccess_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/uaccess_user.c 2004-01-31 02:48:08.000000000 -0500
-@@ -0,0 +1,64 @@
-+/*
-+ * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
-+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <setjmp.h>
-+#include <string.h>
-+
-+/* These are here rather than tt/uaccess.c because skas mode needs them in
-+ * order to do SIGBUS recovery when a tmpfs mount runs out of room.
-+ */
-+
-+unsigned long __do_user_copy(void *to, const void *from, int n,
-+ void **fault_addr, void **fault_catcher,
-+ void (*op)(void *to, const void *from,
-+ int n), int *faulted_out)
-+{
-+ unsigned long *faddrp = (unsigned long *) fault_addr, ret;
-+
-+ sigjmp_buf jbuf;
-+ *fault_catcher = &jbuf;
-+ if(sigsetjmp(jbuf, 1) == 0){
-+ (*op)(to, from, n);
-+ ret = 0;
-+ *faulted_out = 0;
-+ }
-+ else {
-+ ret = *faddrp;
-+ *faulted_out = 1;
-+ }
-+ *fault_addr = NULL;
-+ *fault_catcher = NULL;
-+ return ret;
-+}
-+
-+void __do_copy(void *to, const void *from, int n)
-+{
-+ memcpy(to, from, n);
-+}
-+
-+
-+int __do_copy_to_user(void *to, const void *from, int n,
-+ void **fault_addr, void **fault_catcher)
-+{
-+ unsigned long fault;
-+ int faulted;
-+
-+ fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
-+ __do_copy, &faulted);
-+ if(!faulted) return(0);
-+ else return(n - (fault - (unsigned long) to));
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/um_arch.c um/arch/um/kernel/um_arch.c
---- orig/arch/um/kernel/um_arch.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/um_arch.c 2004-01-10 00:11:09.000000000 -0500
-@@ -0,0 +1,431 @@
-+/*
-+ * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/config.h"
-+#include "linux/kernel.h"
-+#include "linux/sched.h"
-+#include "linux/notifier.h"
-+#include "linux/mm.h"
-+#include "linux/types.h"
-+#include "linux/tty.h"
-+#include "linux/init.h"
-+#include "linux/bootmem.h"
-+#include "linux/spinlock.h"
-+#include "linux/utsname.h"
-+#include "linux/sysrq.h"
-+#include "linux/seq_file.h"
-+#include "linux/delay.h"
-+#include "asm/page.h"
-+#include "asm/pgtable.h"
-+#include "asm/ptrace.h"
-+#include "asm/elf.h"
-+#include "asm/user.h"
-+#include "ubd_user.h"
-+#include "asm/current.h"
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "kern.h"
-+#include "mprot.h"
-+#include "mem_user.h"
-+#include "mem.h"
-+#include "umid.h"
-+#include "initrd.h"
-+#include "init.h"
-+#include "os.h"
-+#include "choose-mode.h"
-+#include "mode_kern.h"
-+#include "mode.h"
-+
-+#define DEFAULT_COMMAND_LINE "root=/dev/ubd0"
-+
-+struct cpuinfo_um boot_cpu_data = {
-+ .loops_per_jiffy = 0,
-+ .pgd_quick = NULL,
-+ .pmd_quick = NULL,
-+ .pte_quick = NULL,
-+ .pgtable_cache_sz = 0,
-+ .ipi_pipe = { -1, -1 }
-+};
-+
-+unsigned long thread_saved_pc(struct thread_struct *thread)
-+{
-+ return(os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas,
-+ thread)));
-+}
-+
-+static int show_cpuinfo(struct seq_file *m, void *v)
-+{
-+ int index = 0;
-+
-+#ifdef CONFIG_SMP
-+ index = (struct cpuinfo_um *)v - cpu_data;
-+ if (!(cpu_online_map & (1 << index)))
-+ return 0;
-+#endif
-+
-+ seq_printf(m, "processor\t: %d\n", index);
-+ seq_printf(m, "vendor_id\t: User Mode Linux\n");
-+ seq_printf(m, "model name\t: UML\n");
-+ seq_printf(m, "mode\t\t: %s\n", CHOOSE_MODE("tt", "skas"));
-+ seq_printf(m, "host\t\t: %s\n", host_info);
-+ seq_printf(m, "bogomips\t: %lu.%02lu\n\n",
-+ loops_per_jiffy/(500000/HZ),
-+ (loops_per_jiffy/(5000/HZ)) % 100);
-+
-+ return(0);
-+}
-+
-+static void *c_start(struct seq_file *m, loff_t *pos)
-+{
-+ return *pos < NR_CPUS ? cpu_data + *pos : NULL;
-+}
-+
-+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
-+{
-+ ++*pos;
-+ return c_start(m, pos);
-+}
-+
-+static void c_stop(struct seq_file *m, void *v)
-+{
-+}
-+
-+struct seq_operations cpuinfo_op = {
-+ .start = c_start,
-+ .next = c_next,
-+ .stop = c_stop,
-+ .show = show_cpuinfo,
-+};
-+
-+pte_t * __bad_pagetable(void)
-+{
-+ panic("Someone should implement __bad_pagetable");
-+ return(NULL);
-+}
-+
-+/* Set in linux_main */
-+unsigned long host_task_size;
-+unsigned long task_size;
-+unsigned long uml_start;
-+
-+/* Set in early boot */
-+unsigned long uml_physmem;
-+unsigned long uml_reserved;
-+unsigned long start_vm;
-+unsigned long end_vm;
-+int ncpus = 1;
-+
-+#ifdef CONFIG_MODE_TT
-+/* Pointer set in linux_main, the array itself is private to each thread,
-+ * and changed at address space creation time so this poses no concurrency
-+ * problems.
-+ */
-+static char *argv1_begin = NULL;
-+static char *argv1_end = NULL;
-+#endif
-+
-+/* Set in early boot */
-+static int have_root __initdata = 0;
-+long physmem_size = 32 * 1024 * 1024;
-+
-+void set_cmdline(char *cmd)
-+{
-+#ifdef CONFIG_MODE_TT
-+ char *umid, *ptr;
-+
-+ if(CHOOSE_MODE(honeypot, 0)) return;
-+
-+ umid = get_umid(1);
-+ if(umid != NULL){
-+ snprintf(argv1_begin,
-+ (argv1_end - argv1_begin) * sizeof(*ptr),
-+ "(%s) ", umid);
-+ ptr = &argv1_begin[strlen(argv1_begin)];
-+ }
-+ else ptr = argv1_begin;
-+
-+ snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), "[%s]", cmd);
-+ memset(argv1_begin + strlen(argv1_begin), '\0',
-+ argv1_end - argv1_begin - strlen(argv1_begin));
-+#endif
-+}
-+
-+static char *usage_string =
-+"User Mode Linux v%s\n"
-+" available at http://user-mode-linux.sourceforge.net/\n\n";
-+
-+static int __init uml_version_setup(char *line, int *add)
-+{
-+ printf("%s\n", system_utsname.release);
-+ exit(0);
-+}
-+
-+__uml_setup("--version", uml_version_setup,
-+"--version\n"
-+" Prints the version number of the kernel.\n\n"
-+);
-+
-+static int __init uml_root_setup(char *line, int *add)
-+{
-+ have_root = 1;
-+ return 0;
-+}
-+
-+__uml_setup("root=", uml_root_setup,
-+"root=<file containing the root fs>\n"
-+" This is actually used by the generic kernel in exactly the same\n"
-+" way as in any other kernel. If you configure a number of block\n"
-+" devices and want to boot off something other than ubd0, you \n"
-+" would use something like:\n"
-+" root=/dev/ubd5\n\n"
-+);
-+
-+#ifdef CONFIG_SMP
-+static int __init uml_ncpus_setup(char *line, int *add)
-+{
-+ if (!sscanf(line, "%d", &ncpus)) {
-+ printf("Couldn't parse [%s]\n", line);
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+__uml_setup("ncpus=", uml_ncpus_setup,
-+"ncpus=<# of desired CPUs>\n"
-+" This tells an SMP kernel how many virtual processors to start.\n\n"
-+);
-+#endif
-+
-+int force_tt = 0;
-+
-+#if defined(CONFIG_MODE_TT) && defined(CONFIG_MODE_SKAS)
-+#define DEFAULT_TT 0
-+
-+static int __init mode_tt_setup(char *line, int *add)
-+{
-+ force_tt = 1;
-+ return(0);
-+}
-+
-+#else
-+#ifdef CONFIG_MODE_SKAS
-+
-+#define DEFAULT_TT 0
-+
-+static int __init mode_tt_setup(char *line, int *add)
-+{
-+ printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n");
-+ return(0);
-+}
-+
-+#else
-+#ifdef CONFIG_MODE_TT
-+
-+#define DEFAULT_TT 1
-+
-+static int __init mode_tt_setup(char *line, int *add)
-+{
-+ printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n");
-+ return(0);
-+}
-+
-+#else
-+
-+#error Either CONFIG_MODE_TT or CONFIG_MODE_SKAS must be enabled
-+
-+#endif
-+#endif
-+#endif
-+
-+__uml_setup("mode=tt", mode_tt_setup,
-+"mode=tt\n"
-+" When both CONFIG_MODE_TT and CONFIG_MODE_SKAS are enabled, this option\n"
-+" forces UML to run in tt (tracing thread) mode. It is not the default\n"
-+" because it's slower and less secure than skas mode.\n\n"
-+);
-+
-+int mode_tt = DEFAULT_TT;
-+
-+static int __init Usage(char *line, int *add)
-+{
-+ const char **p;
-+
-+ printf(usage_string, system_utsname.release);
-+ p = &__uml_help_start;
-+ while (p < &__uml_help_end) {
-+ printf("%s", *p);
-+ p++;
-+ }
-+ exit(0);
-+}
-+
-+__uml_setup("--help", Usage,
-+"--help\n"
-+" Prints this message.\n\n"
-+);
-+
-+static int __init uml_checksetup(char *line, int *add)
-+{
-+ struct uml_param *p;
-+
-+ p = &__uml_setup_start;
-+ while(p < &__uml_setup_end) {
-+ int n;
-+
-+ n = strlen(p->str);
-+ if(!strncmp(line, p->str, n)){
-+ if (p->setup_func(line + n, add)) return 1;
-+ }
-+ p++;
-+ }
-+ return 0;
-+}
-+
-+static void __init uml_postsetup(void)
-+{
-+ initcall_t *p;
-+
-+ p = &__uml_postsetup_start;
-+ while(p < &__uml_postsetup_end){
-+ (*p)();
-+ p++;
-+ }
-+ return;
-+}
-+
-+/* Set during early boot */
-+unsigned long brk_start;
-+unsigned long end_iomem;
-+
-+#define MIN_VMALLOC (32 * 1024 * 1024)
-+
-+int linux_main(int argc, char **argv)
-+{
-+ unsigned long avail;
-+ unsigned long virtmem_size, max_physmem;
-+ unsigned int i, add;
-+
-+ for (i = 1; i < argc; i++){
-+ if((i == 1) && (argv[i][0] == ' ')) continue;
-+ add = 1;
-+ uml_checksetup(argv[i], &add);
-+ if(add) add_arg(saved_command_line, argv[i]);
-+ }
-+ if(have_root == 0) add_arg(saved_command_line, DEFAULT_COMMAND_LINE);
-+
-+ mode_tt = force_tt ? 1 : !can_do_skas();
-+ uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0,
-+ &host_task_size, &task_size);
-+
-+ brk_start = (unsigned long) sbrk(0);
-+ CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start);
-+
-+ uml_physmem = uml_start;
-+
-+ /* Reserve up to 4M after the current brk */
-+ uml_reserved = ROUND_4M(brk_start) + (1 << 22);
-+
-+ setup_machinename(system_utsname.machine);
-+
-+#ifdef CONFIG_MODE_TT
-+ argv1_begin = argv[1];
-+ argv1_end = &argv[1][strlen(argv[1])];
-+#endif
-+
-+ highmem = 0;
-+ iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
-+ max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC;
-+
-+ /* Zones have to begin on a 1 << MAX_ORDER page boundary,
-+ * so this makes sure that's true for highmem
-+ */
-+ max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1);
-+ if(physmem_size + iomem_size > max_physmem){
-+ highmem = physmem_size + iomem_size - max_physmem;
-+ physmem_size -= highmem;
-+#ifndef CONFIG_HIGHMEM
-+ highmem = 0;
-+ printf("CONFIG_HIGHMEM not enabled - physical memory shrunk "
-+ "to %ld bytes\n", physmem_size);
-+#endif
-+ }
-+
-+ high_physmem = uml_physmem + physmem_size;
-+ end_iomem = high_physmem + iomem_size;
-+ high_memory = (void *) end_iomem;
-+
-+ start_vm = VMALLOC_START;
-+
-+ setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
-+ if(init_maps(physmem_size, iomem_size, highmem)){
-+ printf("Failed to allocate mem_map for %ld bytes of physical "
-+ "memory and %ld bytes of highmem\n", physmem_size,
-+ highmem);
-+ exit(1);
-+ }
-+
-+ virtmem_size = physmem_size;
-+ avail = get_kmem_end() - start_vm;
-+ if(physmem_size > avail) virtmem_size = avail;
-+ end_vm = start_vm + virtmem_size;
-+
-+ if(virtmem_size < physmem_size)
-+ printf("Kernel virtual memory size shrunk to %ld bytes\n",
-+ virtmem_size);
-+
-+ uml_postsetup();
-+
-+ init_task.thread.kernel_stack = (unsigned long) &init_task +
-+ 2 * PAGE_SIZE;
-+
-+ task_protections((unsigned long) &init_task);
-+ os_flush_stdout();
-+
-+ return(CHOOSE_MODE(start_uml_tt(), start_uml_skas()));
-+}
-+
-+static int panic_exit(struct notifier_block *self, unsigned long unused1,
-+ void *unused2)
-+{
-+#ifdef CONFIG_SYSRQ
-+ handle_sysrq('p', ¤t->thread.regs, NULL, NULL);
-+#endif
-+ machine_halt();
-+ return(0);
-+}
-+
-+static struct notifier_block panic_exit_notifier = {
-+ .notifier_call = panic_exit,
-+ .next = NULL,
-+ .priority = 0
-+};
-+
-+void __init setup_arch(char **cmdline_p)
-+{
-+ notifier_chain_register(&panic_notifier_list, &panic_exit_notifier);
-+ paging_init();
-+ strcpy(command_line, saved_command_line);
-+ *cmdline_p = command_line;
-+ setup_hostinfo();
-+}
-+
-+void __init check_bugs(void)
-+{
-+ arch_check_bugs();
-+ check_ptrace();
-+ check_sigio();
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/umid.c um/arch/um/kernel/umid.c
---- orig/arch/um/kernel/umid.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/umid.c 2004-01-26 10:13:01.000000000 -0500
-@@ -0,0 +1,327 @@
-+/*
-+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdio.h>
-+#include <unistd.h>
-+#include <errno.h>
-+#include <string.h>
-+#include <stdlib.h>
-+#include <dirent.h>
-+#include <signal.h>
-+#include <sys/stat.h>
-+#include <sys/param.h>
-+#include "user.h"
-+#include "umid.h"
-+#include "init.h"
-+#include "os.h"
-+#include "user_util.h"
-+#include "choose-mode.h"
-+
-+#define UMID_LEN 64
-+#define UML_DIR "~/.uml/"
-+
-+/* Changed by set_umid and make_umid, which are run early in boot */
-+static char umid[UMID_LEN] = { 0 };
-+
-+/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */
-+static char *uml_dir = UML_DIR;
-+
-+/* Changed by set_umid */
-+static int umid_is_random = 1;
-+static int umid_inited = 0;
-+
-+static int make_umid(int (*printer)(const char *fmt, ...));
-+
-+static int __init set_umid(char *name, int is_random,
-+ int (*printer)(const char *fmt, ...))
-+{
-+ if(umid_inited){
-+ (*printer)("Unique machine name can't be set twice\n");
-+ return(-1);
-+ }
-+
-+ if(strlen(name) > UMID_LEN - 1)
-+ (*printer)("Unique machine name is being truncated to %s "
-+ "characters\n", UMID_LEN);
-+ strncpy(umid, name, UMID_LEN - 1);
-+ umid[UMID_LEN - 1] = '\0';
-+
-+ umid_is_random = is_random;
-+ umid_inited = 1;
-+ return 0;
-+}
-+
-+static int __init set_umid_arg(char *name, int *add)
-+{
-+ return(set_umid(name, 0, printf));
-+}
-+
-+__uml_setup("umid=", set_umid_arg,
-+"umid=<name>\n"
-+" This is used to assign a unique identity to this UML machine and\n"
-+" is used for naming the pid file and management console socket.\n\n"
-+);
-+
-+int __init umid_file_name(char *name, char *buf, int len)
-+{
-+ int n;
-+
-+ if(!umid_inited && make_umid(printk)) return(-1);
-+
-+ n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1;
-+ if(n > len){
-+ printk("umid_file_name : buffer too short\n");
-+ return(-1);
-+ }
-+
-+ sprintf(buf, "%s%s/%s", uml_dir, umid, name);
-+ return(0);
-+}
-+
-+extern int tracing_pid;
-+
-+static int __init create_pid_file(void)
-+{
-+ char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
-+ char pid[sizeof("nnnnn\0")];
-+ int fd, n;
-+
-+ if(umid_file_name("pid", file, sizeof(file))) return 0;
-+
-+ fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))),
-+ 0644);
-+ if(fd < 0){
-+ printf("Open of machine pid file \"%s\" failed - "
-+ "err = %d\n", file, -fd);
-+ return 0;
-+ }
-+
-+ sprintf(pid, "%d\n", os_getpid());
-+ n = os_write_file(fd, pid, strlen(pid));
-+ if(n != strlen(pid))
-+ printf("Write of pid file failed - err = %d\n", -n);
-+ os_close_file(fd);
-+ return 0;
-+}
-+
-+static int actually_do_remove(char *dir)
-+{
-+ DIR *directory;
-+ struct dirent *ent;
-+ int len;
-+ char file[256];
-+
-+ directory = opendir(dir);
-+ if(directory == NULL){
-+ printk("actually_do_remove : couldn't open directory '%s', "
-+ "errno = %d\n", dir, errno);
-+ return(1);
-+ }
-+ while((ent = readdir(directory)) != NULL){
-+ if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
-+ continue;
-+ len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1;
-+ if(len > sizeof(file)){
-+ printk("Not deleting '%s' from '%s' - name too long\n",
-+ ent->d_name, dir);
-+ continue;
-+ }
-+ sprintf(file, "%s/%s", dir, ent->d_name);
-+ if(unlink(file) < 0){
-+ printk("actually_do_remove : couldn't remove '%s' "
-+ "from '%s', errno = %d\n", ent->d_name, dir,
-+ errno);
-+ return(1);
-+ }
-+ }
-+ if(rmdir(dir) < 0){
-+ printk("actually_do_remove : couldn't rmdir '%s', "
-+ "errno = %d\n", dir, errno);
-+ return(1);
-+ }
-+ return(0);
-+}
-+
-+void remove_umid_dir(void)
-+{
-+ char dir[strlen(uml_dir) + UMID_LEN + 1];
-+ if(!umid_inited) return;
-+
-+ sprintf(dir, "%s%s", uml_dir, umid);
-+ actually_do_remove(dir);
-+}
-+
-+char *get_umid(int only_if_set)
-+{
-+ if(only_if_set && umid_is_random) return(NULL);
-+ return(umid);
-+}
-+
-+int not_dead_yet(char *dir)
-+{
-+ char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
-+ char pid[sizeof("nnnnn\0")], *end;
-+ int dead, fd, p, n;
-+
-+ sprintf(file, "%s/pid", dir);
-+ dead = 0;
-+ fd = os_open_file(file, of_read(OPENFLAGS()), 0);
-+ if(fd < 0){
-+ if(fd != -ENOENT){
-+ printk("not_dead_yet : couldn't open pid file '%s', "
-+ "err = %d\n", file, -fd);
-+ return(1);
-+ }
-+ dead = 1;
-+ }
-+ if(fd > 0){
-+ n = os_read_file(fd, pid, sizeof(pid));
-+ if(n < 0){
-+ printk("not_dead_yet : couldn't read pid file '%s', "
-+ "err = %d\n", file, -n);
-+ return(1);
-+ }
-+ p = strtoul(pid, &end, 0);
-+ if(end == pid){
-+ printk("not_dead_yet : couldn't parse pid file '%s', "
-+ "errno = %d\n", file, errno);
-+ dead = 1;
-+ }
-+ if(((kill(p, 0) < 0) && (errno == ESRCH)) ||
-+ (p == CHOOSE_MODE(tracing_pid, os_getpid())))
-+ dead = 1;
-+ }
-+ if(!dead) return(1);
-+ return(actually_do_remove(dir));
-+}
-+
-+static int __init set_uml_dir(char *name, int *add)
-+{
-+ if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){
-+ uml_dir = malloc(strlen(name) + 1);
-+ if(uml_dir == NULL){
-+ printf("Failed to malloc uml_dir - error = %d\n",
-+ errno);
-+ uml_dir = name;
-+ /* Return 0 here because do_initcalls doesn't look at
-+ * the return value.
-+ */
-+ return(0);
-+ }
-+ sprintf(uml_dir, "%s/", name);
-+ }
-+ else uml_dir = name;
-+ return(0);
-+}
-+
-+static int __init make_uml_dir(void)
-+{
-+ char dir[MAXPATHLEN + 1] = { '\0' };
-+ int len;
-+
-+ if(*uml_dir == '~'){
-+ char *home = getenv("HOME");
-+
-+ if(home == NULL){
-+ printf("make_uml_dir : no value in environment for "
-+ "$HOME\n");
-+ exit(1);
-+ }
-+ strncpy(dir, home, sizeof(dir));
-+ uml_dir++;
-+ }
-+ len = strlen(dir);
-+ strncat(dir, uml_dir, sizeof(dir) - len);
-+ len = strlen(dir);
-+ if((len > 0) && (len < sizeof(dir) - 1) && (dir[len - 1] != '/')){
-+ dir[len] = '/';
-+ dir[len + 1] = '\0';
-+ }
-+
-+ uml_dir = malloc(strlen(dir) + 1);
-+ if(uml_dir == NULL){
-+ printf("make_uml_dir : malloc failed, errno = %d\n", errno);
-+ exit(1);
-+ }
-+ strcpy(uml_dir, dir);
-+
-+ if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){
-+ printf("Failed to mkdir %s - errno = %i\n", uml_dir, errno);
-+ return(-1);
-+ }
-+ return 0;
-+}
-+
-+static int __init make_umid(int (*printer)(const char *fmt, ...))
-+{
-+ int fd, err;
-+ char tmp[strlen(uml_dir) + UMID_LEN + 1];
-+
-+ strncpy(tmp, uml_dir, sizeof(tmp) - 1);
-+ tmp[sizeof(tmp) - 1] = '\0';
-+
-+ if(!umid_inited){
-+ strcat(tmp, "XXXXXX");
-+ fd = mkstemp(tmp);
-+ if(fd < 0){
-+ (*printer)("make_umid - mkstemp failed, errno = %d\n",
-+ errno);
-+ return(1);
-+ }
-+
-+ os_close_file(fd);
-+ /* There's a nice tiny little race between this unlink and
-+ * the mkdir below. It'd be nice if there were a mkstemp
-+ * for directories.
-+ */
-+ unlink(tmp);
-+ set_umid(&tmp[strlen(uml_dir)], 1, printer);
-+ }
-+
-+ sprintf(tmp, "%s%s", uml_dir, umid);
-+
-+ err = mkdir(tmp, 0777);
-+ if(err < 0){
-+ if(errno == EEXIST){
-+ if(not_dead_yet(tmp)){
-+ (*printer)("umid '%s' is in use\n", umid);
-+ return(-1);
-+ }
-+ err = mkdir(tmp, 0777);
-+ }
-+ }
-+ if(err < 0){
-+ (*printer)("Failed to create %s - errno = %d\n", umid, errno);
-+ return(-1);
-+ }
-+
-+ return(0);
-+}
-+
-+__uml_setup("uml_dir=", set_uml_dir,
-+"uml_dir=<directory>\n"
-+" The location to place the pid and umid files.\n\n"
-+);
-+
-+__uml_postsetup(make_uml_dir);
-+
-+static int __init make_umid_setup(void)
-+{
-+ return(make_umid(printf));
-+}
-+
-+__uml_postsetup(make_umid_setup);
-+__uml_postsetup(create_pid_file);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/kernel/user_syms.c um/arch/um/kernel/user_syms.c
---- orig/arch/um/kernel/user_syms.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/user_syms.c 2004-01-23 00:44:09.000000000 -0500
-@@ -0,0 +1,118 @@
-+#include <stdio.h>
-+#include <unistd.h>
-+#include <dirent.h>
-+#include <fcntl.h>
-+#include <errno.h>
-+#include <utime.h>
-+#include <string.h>
-+#include <sys/stat.h>
-+#include <sys/vfs.h>
-+#include <sys/ioctl.h>
-+#include "user_util.h"
-+#include "mem_user.h"
-+
-+/* XXX All the __CONFIG_* stuff is broken because this file can't include
-+ * config.h
-+ */
-+
-+/* Had to steal this from linux/module.h because that file can't be included
-+ * since this includes various user-level headers.
-+ */
-+
-+struct module_symbol
-+{
-+ unsigned long value;
-+ const char *name;
-+};
-+
-+/* Indirect stringification. */
-+
-+#define __MODULE_STRING_1(x) #x
-+#define __MODULE_STRING(x) __MODULE_STRING_1(x)
-+
-+#if !defined(__AUTOCONF_INCLUDED__)
-+
-+#define __EXPORT_SYMBOL(sym,str) error config_must_be_included_before_module
-+#define EXPORT_SYMBOL(var) error config_must_be_included_before_module
-+#define EXPORT_SYMBOL_NOVERS(var) error config_must_be_included_before_module
-+
-+#elif !defined(__CONFIG_MODULES__)
-+
-+#define __EXPORT_SYMBOL(sym,str)
-+#define EXPORT_SYMBOL(var)
-+#define EXPORT_SYMBOL_NOVERS(var)
-+
-+#else
-+
-+#define __EXPORT_SYMBOL(sym, str) \
-+const char __kstrtab_##sym[] \
-+__attribute__((section(".kstrtab"))) = str; \
-+const struct module_symbol __ksymtab_##sym \
-+__attribute__((section("__ksymtab"))) = \
-+{ (unsigned long)&sym, __kstrtab_##sym }
-+
-+#if defined(__MODVERSIONS__) || !defined(__CONFIG_MODVERSIONS__)
-+#define EXPORT_SYMBOL(var) __EXPORT_SYMBOL(var, __MODULE_STRING(var))
-+#else
-+#define EXPORT_SYMBOL(var) __EXPORT_SYMBOL(var, __MODULE_STRING(__VERSIONED_SYMBOL(var)))
-+#endif
-+
-+#define EXPORT_SYMBOL_NOVERS(var) __EXPORT_SYMBOL(var, __MODULE_STRING(var))
-+
-+#endif
-+
-+EXPORT_SYMBOL(__errno_location);
-+
-+EXPORT_SYMBOL(access);
-+EXPORT_SYMBOL(open);
-+EXPORT_SYMBOL(open64);
-+EXPORT_SYMBOL(close);
-+EXPORT_SYMBOL(read);
-+EXPORT_SYMBOL(write);
-+EXPORT_SYMBOL(dup2);
-+EXPORT_SYMBOL(__xstat);
-+EXPORT_SYMBOL(__lxstat);
-+EXPORT_SYMBOL(__lxstat64);
-+EXPORT_SYMBOL(lseek);
-+EXPORT_SYMBOL(lseek64);
-+EXPORT_SYMBOL(chown);
-+EXPORT_SYMBOL(truncate);
-+EXPORT_SYMBOL(utime);
-+EXPORT_SYMBOL(chmod);
-+EXPORT_SYMBOL(rename);
-+EXPORT_SYMBOL(__xmknod);
-+
-+EXPORT_SYMBOL(symlink);
-+EXPORT_SYMBOL(link);
-+EXPORT_SYMBOL(unlink);
-+EXPORT_SYMBOL(readlink);
-+
-+EXPORT_SYMBOL(mkdir);
-+EXPORT_SYMBOL(rmdir);
-+EXPORT_SYMBOL(opendir);
-+EXPORT_SYMBOL(readdir);
-+EXPORT_SYMBOL(closedir);
-+EXPORT_SYMBOL(seekdir);
-+EXPORT_SYMBOL(telldir);
-+
-+EXPORT_SYMBOL(ioctl);
-+
-+extern ssize_t pread64 (int __fd, void *__buf, size_t __nbytes,
-+ __off64_t __offset);
-+extern ssize_t pwrite64 (int __fd, __const void *__buf, size_t __n,
-+ __off64_t __offset);
-+EXPORT_SYMBOL(pread64);
-+EXPORT_SYMBOL(pwrite64);
-+
-+EXPORT_SYMBOL(statfs);
-+EXPORT_SYMBOL(statfs64);
-+
-+EXPORT_SYMBOL(memcpy);
-+EXPORT_SYMBOL(getuid);
-+
-+EXPORT_SYMBOL(memset);
-+EXPORT_SYMBOL(strstr);
-+EXPORT_SYMBOL(strlen);
-+EXPORT_SYMBOL(printf);
-+
-+EXPORT_SYMBOL(find_iomem);
-diff -Naur -X ../exclude-files orig/arch/um/kernel/user_util.c um/arch/um/kernel/user_util.c
---- orig/arch/um/kernel/user_util.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/kernel/user_util.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,164 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <limits.h>
-+#include <sys/mman.h>
-+#include <sys/stat.h>
-+#include <sys/ptrace.h>
-+#include <sys/utsname.h>
-+#include <sys/param.h>
-+#include <sys/time.h>
-+#include "asm/types.h"
-+#include <ctype.h>
-+#include <signal.h>
-+#include <wait.h>
-+#include <errno.h>
-+#include <stdarg.h>
-+#include <sched.h>
-+#include <termios.h>
-+#include <string.h>
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "user.h"
-+#include "mem_user.h"
-+#include "init.h"
-+#include "helper.h"
-+#include "uml-config.h"
-+
-+#define COMMAND_LINE_SIZE _POSIX_ARG_MAX
-+
-+/* Changed in linux_main and setup_arch, which run before SMP is started */
-+char saved_command_line[COMMAND_LINE_SIZE] = { 0 };
-+char command_line[COMMAND_LINE_SIZE] = { 0 };
-+
-+void add_arg(char *cmd_line, char *arg)
-+{
-+ if (strlen(cmd_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) {
-+ printf("add_arg: Too much command line!\n");
-+ exit(1);
-+ }
-+ if(strlen(cmd_line) > 0) strcat(cmd_line, " ");
-+ strcat(cmd_line, arg);
-+}
-+
-+void stop(void)
-+{
-+ while(1) sleep(1000000);
-+}
-+
-+void stack_protections(unsigned long address)
-+{
-+ int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
-+
-+ if(mprotect((void *) address, page_size(), prot) < 0)
-+ panic("protecting stack failed, errno = %d", errno);
-+}
-+
-+void task_protections(unsigned long address)
-+{
-+ unsigned long guard = address + page_size();
-+ unsigned long stack = guard + page_size();
-+ int prot = 0, pages;
-+#ifdef notdef
-+ if(mprotect((void *) guard, page_size(), prot) < 0)
-+ panic("protecting guard page failed, errno = %d", errno);
-+#endif
-+ pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2;
-+ prot = PROT_READ | PROT_WRITE | PROT_EXEC;
-+ if(mprotect((void *) stack, pages * page_size(), prot) < 0)
-+ panic("protecting stack failed, errno = %d", errno);
-+}
-+
-+int wait_for_stop(int pid, int sig, int cont_type, void *relay)
-+{
-+ sigset_t *relay_signals = relay;
-+ int status, ret;
-+
-+ while(1){
-+ ret = waitpid(pid, &status, WUNTRACED);
-+ if((ret < 0) ||
-+ !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){
-+ if(ret < 0){
-+ if(errno == EINTR) continue;
-+ printk("wait failed, errno = %d\n",
-+ errno);
-+ }
-+ else if(WIFEXITED(status))
-+ printk("process exited with status %d\n",
-+ WEXITSTATUS(status));
-+ else if(WIFSIGNALED(status))
-+ printk("process exited with signal %d\n",
-+ WTERMSIG(status));
-+ else if((WSTOPSIG(status) == SIGVTALRM) ||
-+ (WSTOPSIG(status) == SIGALRM) ||
-+ (WSTOPSIG(status) == SIGIO) ||
-+ (WSTOPSIG(status) == SIGPROF) ||
-+ (WSTOPSIG(status) == SIGCHLD) ||
-+ (WSTOPSIG(status) == SIGWINCH) ||
-+ (WSTOPSIG(status) == SIGINT)){
-+ ptrace(cont_type, pid, 0, WSTOPSIG(status));
-+ continue;
-+ }
-+ else if((relay_signals != NULL) &&
-+ sigismember(relay_signals, WSTOPSIG(status))){
-+ ptrace(cont_type, pid, 0, WSTOPSIG(status));
-+ continue;
-+ }
-+ else printk("process stopped with signal %d\n",
-+ WSTOPSIG(status));
-+ panic("wait_for_stop failed to wait for %d to stop "
-+ "with %d\n", pid, sig);
-+ }
-+ return(status);
-+ }
-+}
-+
-+int raw(int fd, int complain)
-+{
-+ struct termios tt;
-+ int err;
-+
-+ tcgetattr(fd, &tt);
-+ cfmakeraw(&tt);
-+ err = tcsetattr(fd, TCSANOW, &tt);
-+ if((err < 0) && complain){
-+ printk("tcsetattr failed, errno = %d\n", errno);
-+ return(-errno);
-+ }
-+ return(0);
-+}
-+
-+void setup_machinename(char *machine_out)
-+{
-+ struct utsname host;
-+
-+ uname(&host);
-+ strcpy(machine_out, host.machine);
-+}
-+
-+char host_info[(_UTSNAME_LENGTH + 1) * 4 + _UTSNAME_NODENAME_LENGTH + 1];
-+
-+void setup_hostinfo(void)
-+{
-+ struct utsname host;
-+
-+ uname(&host);
-+ sprintf(host_info, "%s %s %s %s %s", host.sysname, host.nodename,
-+ host.release, host.version, host.machine);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/link.ld.in um/arch/um/link.ld.in
---- orig/arch/um/link.ld.in 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/link.ld.in 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,94 @@
-+OUTPUT_FORMAT("ELF_FORMAT")
-+OUTPUT_ARCH(ELF_ARCH)
-+ENTRY(_start)
-+
-+SECTIONS
-+{
-+ . = START() + SIZEOF_HEADERS;
-+
-+ __binary_start = .;
-+ifdef(`MODE_TT', `
-+ .thread_private : {
-+ __start_thread_private = .;
-+ errno = .;
-+ . += 4;
-+ arch/um/kernel/tt/unmap_fin.o (.data)
-+ __end_thread_private = .;
-+ }
-+ . = ALIGN(4096);
-+ .remap : { arch/um/kernel/tt/unmap_fin.o (.text) }
-+')
-+ . = ALIGN(4096); /* Init code and data */
-+ _stext = .;
-+ __init_begin = .;
-+ .text.init : { *(.text.init) }
-+ . = ALIGN(4096);
-+ .text :
-+ {
-+ *(.text)
-+ /* .gnu.warning sections are handled specially by elf32.em. */
-+ *(.gnu.warning)
-+ *(.gnu.linkonce.t*)
-+ }
-+ .fini : { *(.fini) } =0x9090
-+ .rodata : { *(.rodata) *(.gnu.linkonce.r*) }
-+ .rodata1 : { *(.rodata1) }
-+ _etext = .;
-+ PROVIDE (etext = .);
-+
-+ . = ALIGN(4096);
-+ PROVIDE (_sdata = .);
-+
-+include(`arch/um/common.ld.in')
-+
-+ .data :
-+ {
-+ . = ALIGN(KERNEL_STACK_SIZE); /* init_task */
-+ *(.data.init_task)
-+ *(.data)
-+ *(.gnu.linkonce.d*)
-+ CONSTRUCTORS
-+ }
-+ .data1 : { *(.data1) }
-+ .ctors :
-+ {
-+ *(.ctors)
-+ }
-+ .dtors :
-+ {
-+ *(.dtors)
-+ }
-+
-+ .got : { *(.got.plt) *(.got) }
-+ .dynamic : { *(.dynamic) }
-+ /* We want the small data sections together, so single-instruction offsets
-+ can access them all, and initialized data all before uninitialized, so
-+ we can shorten the on-disk segment size. */
-+ .sdata : { *(.sdata) }
-+ _edata = .;
-+ PROVIDE (edata = .);
-+ . = ALIGN(0x1000);
-+ .sbss :
-+ {
-+ __bss_start = .;
-+ PROVIDE(_bss_start = .);
-+ *(.sbss)
-+ *(.scommon)
-+ }
-+ .bss :
-+ {
-+ *(.dynbss)
-+ *(.bss)
-+ *(COMMON)
-+ }
-+ _end = . ;
-+ PROVIDE (end = .);
-+ /* Stabs debugging sections. */
-+ .stab 0 : { *(.stab) }
-+ .stabstr 0 : { *(.stabstr) }
-+ .stab.excl 0 : { *(.stab.excl) }
-+ .stab.exclstr 0 : { *(.stab.exclstr) }
-+ .stab.index 0 : { *(.stab.index) }
-+ .stab.indexstr 0 : { *(.stab.indexstr) }
-+ .comment 0 : { *(.comment) }
-+}
-diff -Naur -X ../exclude-files orig/arch/um/main.c um/arch/um/main.c
---- orig/arch/um/main.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/main.c 2004-01-29 00:48:42.000000000 -0500
-@@ -0,0 +1,199 @@
-+/*
-+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <unistd.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <signal.h>
-+#include <errno.h>
-+#include <sys/resource.h>
-+#include <sys/mman.h>
-+#include <sys/user.h>
-+#include <asm/page.h>
-+#include "user_util.h"
-+#include "kern_util.h"
-+#include "mem_user.h"
-+#include "signal_user.h"
-+#include "user.h"
-+#include "init.h"
-+#include "mode.h"
-+#include "choose-mode.h"
-+#include "uml-config.h"
-+
-+/* Set in set_stklim, which is called from main and __wrap_malloc.
-+ * __wrap_malloc only calls it if main hasn't started.
-+ */
-+unsigned long stacksizelim;
-+
-+/* Set in main */
-+char *linux_prog;
-+
-+#define PGD_BOUND (4 * 1024 * 1024)
-+#define STACKSIZE (8 * 1024 * 1024)
-+#define THREAD_NAME_LEN (256)
-+
-+static void set_stklim(void)
-+{
-+ struct rlimit lim;
-+
-+ if(getrlimit(RLIMIT_STACK, &lim) < 0){
-+ perror("getrlimit");
-+ exit(1);
-+ }
-+ if((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)){
-+ lim.rlim_cur = STACKSIZE;
-+ if(setrlimit(RLIMIT_STACK, &lim) < 0){
-+ perror("setrlimit");
-+ exit(1);
-+ }
-+ }
-+ stacksizelim = (lim.rlim_cur + PGD_BOUND - 1) & ~(PGD_BOUND - 1);
-+}
-+
-+static __init void do_uml_initcalls(void)
-+{
-+ initcall_t *call;
-+
-+ call = &__uml_initcall_start;
-+ while (call < &__uml_initcall_end){;
-+ (*call)();
-+ call++;
-+ }
-+}
-+
-+static void last_ditch_exit(int sig)
-+{
-+ CHOOSE_MODE(kmalloc_ok = 0, (void) 0);
-+ signal(SIGINT, SIG_DFL);
-+ signal(SIGTERM, SIG_DFL);
-+ signal(SIGHUP, SIG_DFL);
-+ uml_cleanup();
-+ exit(1);
-+}
-+
-+extern int uml_exitcode;
-+
-+int main(int argc, char **argv, char **envp)
-+{
-+ char **new_argv;
-+ sigset_t mask;
-+ int ret, i;
-+
-+ /* Enable all signals except SIGIO - in some environments, we can
-+ * enter with some signals blocked
-+ */
-+
-+ sigemptyset(&mask);
-+ sigaddset(&mask, SIGIO);
-+ if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){
-+ perror("sigprocmask");
-+ exit(1);
-+ }
-+
-+#ifdef UML_CONFIG_MODE_TT
-+ /* Allocate memory for thread command lines */
-+ if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){
-+
-+ char padding[THREAD_NAME_LEN] = {
-+ [ 0 ... THREAD_NAME_LEN - 2] = ' ', '\0'
-+ };
-+
-+ new_argv = malloc((argc + 2) * sizeof(char*));
-+ if(!new_argv) {
-+ perror("Allocating extended argv");
-+ exit(1);
-+ }
-+
-+ new_argv[0] = argv[0];
-+ new_argv[1] = padding;
-+
-+ for(i = 2; i <= argc; i++)
-+ new_argv[i] = argv[i - 1];
-+ new_argv[argc + 1] = NULL;
-+
-+ execvp(new_argv[0], new_argv);
-+ perror("execing with extended args");
-+ exit(1);
-+ }
-+#endif
-+
-+ linux_prog = argv[0];
-+
-+ set_stklim();
-+
-+ new_argv = malloc((argc + 1) * sizeof(char *));
-+ if(new_argv == NULL){
-+ perror("Mallocing argv");
-+ exit(1);
-+ }
-+ for(i=0;i<argc;i++){
-+ new_argv[i] = strdup(argv[i]);
-+ if(new_argv[i] == NULL){
-+ perror("Mallocing an arg");
-+ exit(1);
-+ }
-+ }
-+ new_argv[argc] = NULL;
-+
-+ set_handler(SIGINT, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
-+ set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
-+ set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
-+
-+ do_uml_initcalls();
-+ ret = linux_main(argc, argv);
-+
-+ /* Reboot */
-+ if(ret){
-+ printf("\n");
-+
-+ execvp(new_argv[0], new_argv);
-+ perror("Failed to exec kernel");
-+ ret = 1;
-+ }
-+ printf("\n");
-+ return(uml_exitcode);
-+}
-+
-+#define CAN_KMALLOC() \
-+ (kmalloc_ok && CHOOSE_MODE((getpid() != tracing_pid), 1))
-+
-+extern void *__real_malloc(int);
-+
-+void *__wrap_malloc(int size)
-+{
-+ if(CAN_KMALLOC())
-+ return(um_kmalloc(size));
-+ else
-+ return(__real_malloc(size));
-+}
-+
-+void *__wrap_calloc(int n, int size)
-+{
-+ void *ptr = __wrap_malloc(n * size);
-+
-+ if(ptr == NULL) return(NULL);
-+ memset(ptr, 0, n * size);
-+ return(ptr);
-+}
-+
-+extern void __real_free(void *);
-+
-+void __wrap_free(void *ptr)
-+{
-+ if(CAN_KMALLOC()) kfree(ptr);
-+ else __real_free(ptr);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/Makefile um/arch/um/Makefile
---- orig/arch/um/Makefile 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/Makefile 2004-02-14 06:26:41.000000000 -0500
-@@ -0,0 +1,174 @@
-+#
-+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+# Licensed under the GPL
-+#
-+
-+OS := $(shell uname -s)
-+
-+ARCH_DIR = arch/um
-+
-+core-y := kernel sys-$(SUBARCH) os-$(OS)
-+drivers-y := fs drivers
-+subdir-y := $(core-y) $(drivers-y)
-+SUBDIRS += $(foreach dir,$(subdir-y),$(ARCH_DIR)/$(dir))
-+
-+CORE_FILES += $(foreach dir,$(core-y),$(ARCH_DIR)/$(dir)/built-in.o)
-+DRIVERS += $(foreach dir,$(drivers-y),$(ARCH_DIR)/$(dir)/built-in.o)
-+
-+include $(ARCH_DIR)/Makefile-$(SUBARCH)
-+include $(ARCH_DIR)/Makefile-os-$(OS)
-+
-+MAKEFILE-$(CONFIG_MODE_TT) += Makefile-tt
-+MAKEFILE-$(CONFIG_MODE_SKAS) += Makefile-skas
-+
-+ifneq ($(MAKEFILE-y),)
-+ include $(addprefix $(ARCH_DIR)/,$(MAKEFILE-y))
-+endif
-+
-+EXTRAVERSION := $(EXTRAVERSION)-1um
-+
-+include/linux/version.h: arch/$(ARCH)/Makefile
-+
-+# Recalculate MODLIB to reflect the EXTRAVERSION changes (via KERNELRELEASE)
-+# The way the toplevel Makefile is written EXTRAVERSION is not supposed
-+# to be changed outside the toplevel Makefile, but recalculating MODLIB is
-+# a sufficient workaround until we no longer need architecture dependent
-+# EXTRAVERSION...
-+MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
-+
-+ifeq ($(CONFIG_DEBUGSYM),y)
-+CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS))
-+endif
-+
-+CFLAGS-$(CONFIG_DEBUGSYM) += -g
-+
-+ARCH_INCLUDE = -I$(TOPDIR)/$(ARCH_DIR)/include
-+
-+# -Derrno=kernel_errno - This turns all kernel references to errno into
-+# kernel_errno to separate them from the libc errno. This allows -fno-common
-+# in CFLAGS. Otherwise, it would cause ld to complain about the two different
-+# errnos.
-+
-+CFLAGS += $(ARCH_CFLAGS) $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
-+ -D_LARGEFILE64_SOURCE $(ARCH_INCLUDE) -Derrno=kernel_errno \
-+ $(MODE_INCLUDE)
-+
-+LINKFLAGS += -r
-+
-+LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
-+
-+# These are needed for clean and mrproper, since in that case .config is not
-+# included; the values here are meaningless
-+
-+CONFIG_NEST_LEVEL ?= 0
-+CONFIG_KERNEL_HALF_GIGS ?= 0
-+
-+SIZE = (($(CONFIG_NEST_LEVEL) + $(CONFIG_KERNEL_HALF_GIGS)) * 0x20000000)
-+
-+# These aren't in Makefile-tt because they are needed in the !CONFIG_MODE_TT +
-+# CONFIG_MODE_SKAS + CONFIG_STATIC_LINK case.
-+
-+LINK_TT = -static
-+LD_SCRIPT_TT := link.ld
-+
-+ifeq ($(CONFIG_STATIC_LINK),y)
-+ LINK-y += $(LINK_TT)
-+ LD_SCRIPT-y := $(LD_SCRIPT_TT)
-+else
-+ifeq ($(CONFIG_MODE_TT),y)
-+ LINK-y += $(LINK_TT)
-+ LD_SCRIPT-y := $(LD_SCRIPT_TT)
-+else
-+ifeq ($(CONFIG_MODE_SKAS),y)
-+ LINK-y += $(LINK_SKAS)
-+ LD_SCRIPT-y := $(LD_SCRIPT_SKAS)
-+endif
-+endif
-+endif
-+
-+LD_SCRIPT-y := $(ARCH_DIR)/$(LD_SCRIPT-y)
-+M4_MODE_TT := $(shell [ "$(CONFIG_MODE_TT)" = "y" ] && echo -DMODE_TT)
-+
-+$(LD_SCRIPT-y): $(LD_SCRIPT-y).in
-+ pages=$$(( 1 << $(CONFIG_KERNEL_STACK_ORDER) )) ; \
-+ m4 -DSTART=$$(($(TOP_ADDR) - $(SIZE))) -DELF_ARCH=$(ELF_ARCH) \
-+ -DELF_FORMAT=$(ELF_FORMAT) $(M4_MODE_TT) \
-+ -DKERNEL_STACK_SIZE=$$(( 4096 * $$pages )) $< > $@
-+
-+SYMLINK_HEADERS = archparam.h system.h sigcontext.h processor.h ptrace.h \
-+ arch-signal.h
-+SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header))
-+
-+ARCH_SYMLINKS = include/asm-um/arch arch/um/include/sysdep arch/um/os \
-+ $(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h
-+
-+ifeq ($(CONFIG_MODE_SKAS), y)
-+$(SYS_HEADERS) : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h
-+endif
-+
-+GEN_HEADERS += $(ARCH_DIR)/include/task.h $(ARCH_DIR)/include/kern_constants.h
-+
-+setup: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS)
-+
-+linux: setup $(ARCH_DIR)/main.o vmlinux $(LD_SCRIPT-y)
-+ mv vmlinux vmlinux.o
-+ $(CC) -Wl,-T,$(LD_SCRIPT-y) $(LINK-y) $(LINK_WRAPS) \
-+ -o linux $(ARCH_DIR)/main.o vmlinux.o -L/usr/lib -lutil
-+
-+USER_CFLAGS := $(patsubst -I%,,$(CFLAGS))
-+USER_CFLAGS := $(patsubst -Derrno=kernel_errno,,$(USER_CFLAGS))
-+USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \
-+ $(MODE_INCLUDE)
-+
-+# To get a definition of F_SETSIG
-+USER_CFLAGS += -D_GNU_SOURCE
-+
-+CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/link.ld $(ARCH_DIR)/dyn_link.ld \
-+ $(GEN_HEADERS) $(ARCH_DIR)/include/uml-config.h
-+
-+$(ARCH_DIR)/main.o: $(ARCH_DIR)/main.c
-+ $(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
-+
-+archmrproper:
-+ rm -f $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) include/asm \
-+ $(LD_SCRIPT) $(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS))
-+
-+archclean: sysclean
-+ find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
-+ -o -name '*.gcov' \) -type f -print | xargs rm -f
-+ cd $(ARCH_DIR) ; \
-+ for dir in $(subdir-y) util ; do $(MAKE) -C $$dir clean; done
-+
-+archdep:
-+
-+$(SYMLINK_HEADERS):
-+ cd $(TOPDIR)/$(dir $@) ; \
-+ ln -sf $(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $(notdir $@)
-+
-+include/asm-um/arch:
-+ cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch
-+
-+arch/um/include/sysdep:
-+ cd $(TOPDIR)/arch/um/include && ln -sf sysdep-$(SUBARCH) sysdep
-+
-+arch/um/os:
-+ cd $(ARCH_DIR) && ln -sf os-$(OS) os
-+
-+$(ARCH_DIR)/include/task.h : $(ARCH_DIR)/util/mk_task
-+ $< > $@
-+
-+$(ARCH_DIR)/include/kern_constants.h : $(ARCH_DIR)/util/mk_constants
-+ $< > $@
-+
-+$(ARCH_DIR)/include/uml-config.h : $(TOPDIR)/include/linux/autoconf.h
-+ sed 's/ CONFIG/ UML_CONFIG/' $(TOPDIR)/include/linux/autoconf.h > $@
-+
-+$(ARCH_DIR)/util/mk_task : $(ARCH_DIR)/util/mk_task_user.c \
-+ $(ARCH_DIR)/util/mk_task_kern.c $(SYS_HEADERS)
-+ $(MAKE) $(MFLAGS) -C $(ARCH_DIR)/util mk_task
-+
-+$(ARCH_DIR)/util/mk_constants : $(ARCH_DIR)/util/mk_constants_user.c \
-+ $(ARCH_DIR)/util/mk_constants_kern.c
-+ $(MAKE) $(MFLAGS) -C $(ARCH_DIR)/util mk_constants
-+
-+export SUBARCH USER_CFLAGS OS
-diff -Naur -X ../exclude-files orig/arch/um/Makefile-i386 um/arch/um/Makefile-i386
---- orig/arch/um/Makefile-i386 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/Makefile-i386 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,35 @@
-+ifeq ($(CONFIG_HOST_2G_2G), y)
-+TOP_ADDR = 0x80000000
-+else
-+TOP_ADDR = 0xc0000000
-+endif
-+
-+ARCH_CFLAGS = -U__$(SUBARCH)__ -U$(SUBARCH) -DUM_FASTCALL
-+ELF_ARCH = $(SUBARCH)
-+ELF_FORMAT = elf32-$(SUBARCH)
-+
-+I386_H = $(ARCH_DIR)/include/sysdep-i386
-+SYS = $(ARCH_DIR)/sys-i386
-+UTIL = $(SYS)/util
-+SUBDIRS += $(UTIL)
-+
-+SYS_HEADERS = $(I386_H)/sc.h $(I386_H)/thread.h
-+
-+$(I386_H)/sc.h : $(UTIL)/mk_sc
-+ $(UTIL)/mk_sc > $@
-+
-+$(I386_H)/thread.h : $(UTIL)/mk_thread
-+ $(UTIL)/mk_thread > $@
-+
-+$(UTIL)/mk_sc : $(UTIL)/mk_sc.c
-+ $(MAKE) -C $(UTIL) mk_sc
-+
-+$(UTIL)/mk_thread : $(UTIL)/mk_thread_user.c $(UTIL)/mk_thread_kern.c \
-+ $(I386_H)/sc.h
-+ $(MAKE) -C $(UTIL) mk_thread
-+
-+sysclean :
-+ rm -f $(SYS_HEADERS)
-+ $(MAKE) -C $(UTIL) clean
-+ $(MAKE) -C $(SYS) clean
-+
-diff -Naur -X ../exclude-files orig/arch/um/Makefile-ia64 um/arch/um/Makefile-ia64
---- orig/arch/um/Makefile-ia64 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/Makefile-ia64 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1 @@
-+START_ADDR = 0x1000000000000000
-diff -Naur -X ../exclude-files orig/arch/um/Makefile-os-Linux um/arch/um/Makefile-os-Linux
---- orig/arch/um/Makefile-os-Linux 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/Makefile-os-Linux 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,7 @@
-+#
-+# Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+# Licensed under the GPL
-+#
-+
-+SUBDIRS += $(ARCH_DIR)/os-$(OS)/drivers
-+DRIVERS += $(ARCH_DIR)/os-$(OS)/drivers/drivers.o
-diff -Naur -X ../exclude-files orig/arch/um/Makefile-ppc um/arch/um/Makefile-ppc
---- orig/arch/um/Makefile-ppc 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/Makefile-ppc 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,9 @@
-+ifeq ($(CONFIG_HOST_2G_2G), y)
-+START_ADDR = 0x80000000
-+else
-+START_ADDR = 0xc0000000
-+endif
-+ARCH_CFLAGS = -U__powerpc__ -D__UM_PPC__
-+
-+# The arch is ppc, but the elf32 name is powerpc
-+ELF_SUBARCH = powerpc
-diff -Naur -X ../exclude-files orig/arch/um/Makefile-skas um/arch/um/Makefile-skas
---- orig/arch/um/Makefile-skas 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/Makefile-skas 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,20 @@
-+#
-+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+# Licensed under the GPL
-+#
-+
-+PROFILE += -pg
-+
-+CFLAGS-$(CONFIG_GCOV) += -fprofile-arcs -ftest-coverage
-+CFLAGS-$(CONFIG_GPROF) += $(PROFILE)
-+LINK-$(CONFIG_GPROF) += $(PROFILE)
-+
-+MODE_INCLUDE += -I$(TOPDIR)/$(ARCH_DIR)/kernel/skas/include
-+
-+LINK_SKAS = -Wl,-rpath,/lib
-+LD_SCRIPT_SKAS = dyn_link.ld
-+
-+GEN_HEADERS += $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h
-+
-+$(ARCH_DIR)/kernel/skas/include/skas_ptregs.h :
-+ $(MAKE) -C $(ARCH_DIR)/kernel/skas include/skas_ptregs.h
-diff -Naur -X ../exclude-files orig/arch/um/Makefile-tt um/arch/um/Makefile-tt
---- orig/arch/um/Makefile-tt 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/Makefile-tt 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,7 @@
-+#
-+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+# Licensed under the GPL
-+#
-+
-+MODE_INCLUDE += -I$(TOPDIR)/$(ARCH_DIR)/kernel/tt/include
-+
-diff -Naur -X ../exclude-files orig/arch/um/os-Linux/drivers/etap.h um/arch/um/os-Linux/drivers/etap.h
---- orig/arch/um/os-Linux/drivers/etap.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/os-Linux/drivers/etap.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,27 @@
-+/*
-+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "net_user.h"
-+
-+struct ethertap_data {
-+ char *dev_name;
-+ char *gate_addr;
-+ int data_fd;
-+ int control_fd;
-+ void *dev;
-+};
-+
-+extern struct net_user_info ethertap_user_info;
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/os-Linux/drivers/ethertap_kern.c um/arch/um/os-Linux/drivers/ethertap_kern.c
---- orig/arch/um/os-Linux/drivers/ethertap_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/os-Linux/drivers/ethertap_kern.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,122 @@
-+/*
-+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
-+ * James Leu (jleu@mindspring.net).
-+ * Copyright (C) 2001 by various other people who didn't put their name here.
-+ * Licensed under the GPL.
-+ */
-+
-+#include "linux/init.h"
-+#include "linux/netdevice.h"
-+#include "linux/etherdevice.h"
-+#include "linux/init.h"
-+#include "net_kern.h"
-+#include "net_user.h"
-+#include "etap.h"
-+
-+struct ethertap_init {
-+ char *dev_name;
-+ char *gate_addr;
-+};
-+
-+static void etap_init(struct net_device *dev, void *data)
-+{
-+ struct uml_net_private *pri;
-+ struct ethertap_data *epri;
-+ struct ethertap_init *init = data;
-+
-+ init_etherdev(dev, 0);
-+ pri = dev->priv;
-+ epri = (struct ethertap_data *) pri->user;
-+ *epri = ((struct ethertap_data)
-+ { .dev_name = init->dev_name,
-+ .gate_addr = init->gate_addr,
-+ .data_fd = -1,
-+ .control_fd = -1,
-+ .dev = dev });
-+
-+ printk("ethertap backend - %s", epri->dev_name);
-+ if(epri->gate_addr != NULL)
-+ printk(", IP = %s", epri->gate_addr);
-+ printk("\n");
-+}
-+
-+static int etap_read(int fd, struct sk_buff **skb, struct uml_net_private *lp)
-+{
-+ int len;
-+
-+ *skb = ether_adjust_skb(*skb, ETH_HEADER_ETHERTAP);
-+ if(*skb == NULL) return(-ENOMEM);
-+ len = net_recvfrom(fd, (*skb)->mac.raw,
-+ (*skb)->dev->mtu + 2 * ETH_HEADER_ETHERTAP);
-+ if(len <= 0) return(len);
-+ skb_pull(*skb, 2);
-+ len -= 2;
-+ return(len);
-+}
-+
-+static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
-+{
-+ if(skb_headroom(*skb) < 2){
-+ struct sk_buff *skb2;
-+
-+ skb2 = skb_realloc_headroom(*skb, 2);
-+ dev_kfree_skb(*skb);
-+ if (skb2 == NULL) return(-ENOMEM);
-+ *skb = skb2;
-+ }
-+ skb_push(*skb, 2);
-+ return(net_send(fd, (*skb)->data, (*skb)->len));
-+}
-+
-+struct net_kern_info ethertap_kern_info = {
-+ .init = etap_init,
-+ .protocol = eth_protocol,
-+ .read = etap_read,
-+ .write = etap_write,
-+};
-+
-+int ethertap_setup(char *str, char **mac_out, void *data)
-+{
-+ struct ethertap_init *init = data;
-+
-+ *init = ((struct ethertap_init)
-+ { .dev_name = NULL,
-+ .gate_addr = NULL });
-+ if(tap_setup_common(str, "ethertap", &init->dev_name, mac_out,
-+ &init->gate_addr))
-+ return(0);
-+ if(init->dev_name == NULL){
-+ printk("ethertap_setup : Missing tap device name\n");
-+ return(0);
-+ }
-+
-+ return(1);
-+}
-+
-+static struct transport ethertap_transport = {
-+ .list = LIST_HEAD_INIT(ethertap_transport.list),
-+ .name = "ethertap",
-+ .setup = ethertap_setup,
-+ .user = ðertap_user_info,
-+ .kern = ðertap_kern_info,
-+ .private_size = sizeof(struct ethertap_data),
-+};
-+
-+static int register_ethertap(void)
-+{
-+ register_transport(ðertap_transport);
-+ return(1);
-+}
-+
-+__initcall(register_ethertap);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/os-Linux/drivers/ethertap_user.c um/arch/um/os-Linux/drivers/ethertap_user.c
---- orig/arch/um/os-Linux/drivers/ethertap_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/os-Linux/drivers/ethertap_user.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,238 @@
-+/*
-+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
-+ * James Leu (jleu@mindspring.net).
-+ * Copyright (C) 2001 by various other people who didn't put their name here.
-+ * Licensed under the GPL.
-+ */
-+
-+#include <stdio.h>
-+#include <unistd.h>
-+#include <stddef.h>
-+#include <stdlib.h>
-+#include <sys/errno.h>
-+#include <sys/socket.h>
-+#include <sys/wait.h>
-+#include <sys/un.h>
-+#include <net/if.h>
-+#include "user.h"
-+#include "kern_util.h"
-+#include "net_user.h"
-+#include "etap.h"
-+#include "helper.h"
-+#include "os.h"
-+
-+#define MAX_PACKET ETH_MAX_PACKET
-+
-+void etap_user_init(void *data, void *dev)
-+{
-+ struct ethertap_data *pri = data;
-+
-+ pri->dev = dev;
-+}
-+
-+struct addr_change {
-+ enum { ADD_ADDR, DEL_ADDR } what;
-+ unsigned char addr[4];
-+ unsigned char netmask[4];
-+};
-+
-+static void etap_change(int op, unsigned char *addr, unsigned char *netmask,
-+ int fd)
-+{
-+ struct addr_change change;
-+ void *output;
-+ int n;
-+
-+ change.what = op;
-+ memcpy(change.addr, addr, sizeof(change.addr));
-+ memcpy(change.netmask, netmask, sizeof(change.netmask));
-+ n = os_write_file(fd, &change, sizeof(change));
-+ if(n != sizeof(change))
-+ printk("etap_change - request failed, err = %d\n", -n);
-+ output = um_kmalloc(page_size());
-+ if(output == NULL)
-+ printk("etap_change : Failed to allocate output buffer\n");
-+ read_output(fd, output, page_size());
-+ if(output != NULL){
-+ printk("%s", output);
-+ kfree(output);
-+ }
-+}
-+
-+static void etap_open_addr(unsigned char *addr, unsigned char *netmask,
-+ void *arg)
-+{
-+ etap_change(ADD_ADDR, addr, netmask, *((int *) arg));
-+}
-+
-+static void etap_close_addr(unsigned char *addr, unsigned char *netmask,
-+ void *arg)
-+{
-+ etap_change(DEL_ADDR, addr, netmask, *((int *) arg));
-+}
-+
-+struct etap_pre_exec_data {
-+ int control_remote;
-+ int control_me;
-+ int data_me;
-+};
-+
-+static void etap_pre_exec(void *arg)
-+{
-+ struct etap_pre_exec_data *data = arg;
-+
-+ dup2(data->control_remote, 1);
-+ os_close_file(data->data_me);
-+ os_close_file(data->control_me);
-+}
-+
-+static int etap_tramp(char *dev, char *gate, int control_me,
-+ int control_remote, int data_me, int data_remote)
-+{
-+ struct etap_pre_exec_data pe_data;
-+ int pid, status, err, n;
-+ char version_buf[sizeof("nnnnn\0")];
-+ char data_fd_buf[sizeof("nnnnnn\0")];
-+ char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
-+ char *setup_args[] = { "uml_net", version_buf, "ethertap", dev,
-+ data_fd_buf, gate_buf, NULL };
-+ char *nosetup_args[] = { "uml_net", version_buf, "ethertap",
-+ dev, data_fd_buf, NULL };
-+ char **args, c;
-+
-+ sprintf(data_fd_buf, "%d", data_remote);
-+ sprintf(version_buf, "%d", UML_NET_VERSION);
-+ if(gate != NULL){
-+ strcpy(gate_buf, gate);
-+ args = setup_args;
-+ }
-+ else args = nosetup_args;
-+
-+ err = 0;
-+ pe_data.control_remote = control_remote;
-+ pe_data.control_me = control_me;
-+ pe_data.data_me = data_me;
-+ pid = run_helper(etap_pre_exec, &pe_data, args, NULL);
-+
-+ if(pid < 0) err = pid;
-+ os_close_file(data_remote);
-+ os_close_file(control_remote);
-+ n = os_read_file(control_me, &c, sizeof(c));
-+ if(n != sizeof(c)){
-+ printk("etap_tramp : read of status failed, err = %d\n", -n);
-+ return(-EINVAL);
-+ }
-+ if(c != 1){
-+ printk("etap_tramp : uml_net failed\n");
-+ err = -EINVAL;
-+ if(waitpid(pid, &status, 0) < 0)
-+ err = -errno;
-+ else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1))
-+ printk("uml_net didn't exit with status 1\n");
-+ }
-+ return(err);
-+}
-+
-+static int etap_open(void *data)
-+{
-+ struct ethertap_data *pri = data;
-+ char *output;
-+ int data_fds[2], control_fds[2], err, output_len;
-+
-+ err = tap_open_common(pri->dev, pri->gate_addr);
-+ if(err) return(err);
-+
-+ err = os_pipe(data_fds, 0, 0);
-+ if(err < 0){
-+ printk("data os_pipe failed - err = %d\n", -err);
-+ return(err);
-+ }
-+
-+ err = os_pipe(control_fds, 1, 0);
-+ if(err < 0){
-+ printk("control os_pipe failed - err = %d\n", -err);
-+ return(err);
-+ }
-+
-+ err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0],
-+ control_fds[1], data_fds[0], data_fds[1]);
-+ output_len = page_size();
-+ output = um_kmalloc(output_len);
-+ read_output(control_fds[0], output, output_len);
-+
-+ if(output == NULL)
-+ printk("etap_open : failed to allocate output buffer\n");
-+ else {
-+ printk("%s", output);
-+ kfree(output);
-+ }
-+
-+ if(err < 0){
-+ printk("etap_tramp failed - err = %d\n", -err);
-+ return(err);
-+ }
-+
-+ pri->data_fd = data_fds[0];
-+ pri->control_fd = control_fds[0];
-+ iter_addresses(pri->dev, etap_open_addr, &pri->control_fd);
-+ return(data_fds[0]);
-+}
-+
-+static void etap_close(int fd, void *data)
-+{
-+ struct ethertap_data *pri = data;
-+
-+ iter_addresses(pri->dev, etap_close_addr, &pri->control_fd);
-+ os_close_file(fd);
-+ os_shutdown_socket(pri->data_fd, 1, 1);
-+ os_close_file(pri->data_fd);
-+ pri->data_fd = -1;
-+ os_close_file(pri->control_fd);
-+ pri->control_fd = -1;
-+}
-+
-+static int etap_set_mtu(int mtu, void *data)
-+{
-+ return(mtu);
-+}
-+
-+static void etap_add_addr(unsigned char *addr, unsigned char *netmask,
-+ void *data)
-+{
-+ struct ethertap_data *pri = data;
-+
-+ tap_check_ips(pri->gate_addr, addr);
-+ if(pri->control_fd == -1) return;
-+ etap_open_addr(addr, netmask, &pri->control_fd);
-+}
-+
-+static void etap_del_addr(unsigned char *addr, unsigned char *netmask,
-+ void *data)
-+{
-+ struct ethertap_data *pri = data;
-+
-+ if(pri->control_fd == -1) return;
-+ etap_close_addr(addr, netmask, &pri->control_fd);
-+}
-+
-+struct net_user_info ethertap_user_info = {
-+ .init = etap_user_init,
-+ .open = etap_open,
-+ .close = etap_close,
-+ .remove = NULL,
-+ .set_mtu = etap_set_mtu,
-+ .add_address = etap_add_addr,
-+ .delete_address = etap_del_addr,
-+ .max_packet = MAX_PACKET - ETH_HEADER_ETHERTAP
-+};
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/os-Linux/drivers/Makefile um/arch/um/os-Linux/drivers/Makefile
---- orig/arch/um/os-Linux/drivers/Makefile 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/os-Linux/drivers/Makefile 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,31 @@
-+#
-+# Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
-+# Licensed under the GPL
-+#
-+
-+O_TARGET := drivers.o
-+
-+list-multi := tuntap.o ethertap.o
-+
-+ethertap-objs := ethertap_kern.o ethertap_user.o
-+tuntap-objs := tuntap_kern.o tuntap_user.o
-+
-+obj-y =
-+obj-$(CONFIG_UML_NET_ETHERTAP) += ethertap.o
-+obj-$(CONFIG_UML_NET_TUNTAP) += tuntap.o
-+
-+USER_SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y)),$($(f)-objs))
-+
-+USER_OBJS = $(filter %_user.o,$(obj-y) $(USER_SINGLE_OBJS))
-+
-+include $(TOPDIR)/Rules.make
-+
-+$(USER_OBJS) : %.o: %.c
-+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $<
-+
-+ethertap.o : $(ethertap-objs)
-+
-+tuntap.o : $(tuntap-objs)
-+
-+$(list-multi) : # This doesn't work, but should : '%.o : $(%-objs)'
-+ $(LD) $(LD_RFLAG) -r -o $@ $($(patsubst %.o,%,$@)-objs)
-diff -Naur -X ../exclude-files orig/arch/um/os-Linux/drivers/tuntap.h um/arch/um/os-Linux/drivers/tuntap.h
---- orig/arch/um/os-Linux/drivers/tuntap.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/os-Linux/drivers/tuntap.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,32 @@
-+/*
-+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UM_TUNTAP_H
-+#define __UM_TUNTAP_H
-+
-+#include "net_user.h"
-+
-+struct tuntap_data {
-+ char *dev_name;
-+ int fixed_config;
-+ char *gate_addr;
-+ int fd;
-+ void *dev;
-+};
-+
-+extern struct net_user_info tuntap_user_info;
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/os-Linux/drivers/tuntap_kern.c um/arch/um/os-Linux/drivers/tuntap_kern.c
---- orig/arch/um/os-Linux/drivers/tuntap_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/os-Linux/drivers/tuntap_kern.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,105 @@
-+/*
-+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/stddef.h"
-+#include "linux/netdevice.h"
-+#include "linux/etherdevice.h"
-+#include "linux/skbuff.h"
-+#include "linux/init.h"
-+#include "asm/errno.h"
-+#include "net_kern.h"
-+#include "net_user.h"
-+#include "tuntap.h"
-+
-+struct tuntap_init {
-+ char *dev_name;
-+ char *gate_addr;
-+};
-+
-+static void tuntap_init(struct net_device *dev, void *data)
-+{
-+ struct uml_net_private *pri;
-+ struct tuntap_data *tpri;
-+ struct tuntap_init *init = data;
-+
-+ init_etherdev(dev, 0);
-+ pri = dev->priv;
-+ tpri = (struct tuntap_data *) pri->user;
-+ *tpri = ((struct tuntap_data)
-+ { .dev_name = init->dev_name,
-+ .fixed_config = (init->dev_name != NULL),
-+ .gate_addr = init->gate_addr,
-+ .fd = -1,
-+ .dev = dev });
-+ printk("TUN/TAP backend - ");
-+ if(tpri->gate_addr != NULL)
-+ printk("IP = %s", tpri->gate_addr);
-+ printk("\n");
-+}
-+
-+static int tuntap_read(int fd, struct sk_buff **skb,
-+ struct uml_net_private *lp)
-+{
-+ *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER);
-+ if(*skb == NULL) return(-ENOMEM);
-+ return(net_read(fd, (*skb)->mac.raw,
-+ (*skb)->dev->mtu + ETH_HEADER_OTHER));
-+}
-+
-+static int tuntap_write(int fd, struct sk_buff **skb,
-+ struct uml_net_private *lp)
-+{
-+ return(net_write(fd, (*skb)->data, (*skb)->len));
-+}
-+
-+struct net_kern_info tuntap_kern_info = {
-+ .init = tuntap_init,
-+ .protocol = eth_protocol,
-+ .read = tuntap_read,
-+ .write = tuntap_write,
-+};
-+
-+int tuntap_setup(char *str, char **mac_out, void *data)
-+{
-+ struct tuntap_init *init = data;
-+
-+ *init = ((struct tuntap_init)
-+ { .dev_name = NULL,
-+ .gate_addr = NULL });
-+ if(tap_setup_common(str, "tuntap", &init->dev_name, mac_out,
-+ &init->gate_addr))
-+ return(0);
-+
-+ return(1);
-+}
-+
-+static struct transport tuntap_transport = {
-+ .list = LIST_HEAD_INIT(tuntap_transport.list),
-+ .name = "tuntap",
-+ .setup = tuntap_setup,
-+ .user = &tuntap_user_info,
-+ .kern = &tuntap_kern_info,
-+ .private_size = sizeof(struct tuntap_data),
-+ .setup_size = sizeof(struct tuntap_init),
-+};
-+
-+static int register_tuntap(void)
-+{
-+ register_transport(&tuntap_transport);
-+ return(1);
-+}
-+
-+__initcall(register_tuntap);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/os-Linux/drivers/tuntap_user.c um/arch/um/os-Linux/drivers/tuntap_user.c
---- orig/arch/um/os-Linux/drivers/tuntap_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/os-Linux/drivers/tuntap_user.c 2003-11-12 00:02:30.000000000 -0500
-@@ -0,0 +1,224 @@
-+/*
-+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdio.h>
-+#include <stddef.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <errno.h>
-+#include <sys/wait.h>
-+#include <sys/socket.h>
-+#include <sys/un.h>
-+#include <sys/uio.h>
-+#include <sys/ioctl.h>
-+#include <net/if.h>
-+#include <linux/if_tun.h>
-+#include "net_user.h"
-+#include "tuntap.h"
-+#include "kern_util.h"
-+#include "user.h"
-+#include "helper.h"
-+#include "os.h"
-+
-+#define MAX_PACKET ETH_MAX_PACKET
-+
-+void tuntap_user_init(void *data, void *dev)
-+{
-+ struct tuntap_data *pri = data;
-+
-+ pri->dev = dev;
-+}
-+
-+static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask,
-+ void *data)
-+{
-+ struct tuntap_data *pri = data;
-+
-+ tap_check_ips(pri->gate_addr, addr);
-+ if((pri->fd == -1) || pri->fixed_config) return;
-+ open_addr(addr, netmask, pri->dev_name);
-+}
-+
-+static void tuntap_del_addr(unsigned char *addr, unsigned char *netmask,
-+ void *data)
-+{
-+ struct tuntap_data *pri = data;
-+
-+ if((pri->fd == -1) || pri->fixed_config) return;
-+ close_addr(addr, netmask, pri->dev_name);
-+}
-+
-+struct tuntap_pre_exec_data {
-+ int stdout;
-+ int close_me;
-+};
-+
-+static void tuntap_pre_exec(void *arg)
-+{
-+ struct tuntap_pre_exec_data *data = arg;
-+
-+ dup2(data->stdout, 1);
-+ os_close_file(data->close_me);
-+}
-+
-+static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
-+ char *buffer, int buffer_len, int *used_out)
-+{
-+ struct tuntap_pre_exec_data data;
-+ char version_buf[sizeof("nnnnn\0")];
-+ char *argv[] = { "uml_net", version_buf, "tuntap", "up", gate,
-+ NULL };
-+ char buf[CMSG_SPACE(sizeof(*fd_out))];
-+ struct msghdr msg;
-+ struct cmsghdr *cmsg;
-+ struct iovec iov;
-+ int pid, n;
-+
-+ sprintf(version_buf, "%d", UML_NET_VERSION);
-+
-+ data.stdout = remote;
-+ data.close_me = me;
-+
-+ pid = run_helper(tuntap_pre_exec, &data, argv, NULL);
-+
-+ if(pid < 0) return(-pid);
-+
-+ os_close_file(remote);
-+
-+ msg.msg_name = NULL;
-+ msg.msg_namelen = 0;
-+ if(buffer != NULL){
-+ iov = ((struct iovec) { buffer, buffer_len });
-+ msg.msg_iov = &iov;
-+ msg.msg_iovlen = 1;
-+ }
-+ else {
-+ msg.msg_iov = NULL;
-+ msg.msg_iovlen = 0;
-+ }
-+ msg.msg_control = buf;
-+ msg.msg_controllen = sizeof(buf);
-+ msg.msg_flags = 0;
-+ n = recvmsg(me, &msg, 0);
-+ *used_out = n;
-+ if(n < 0){
-+ printk("tuntap_open_tramp : recvmsg failed - errno = %d\n",
-+ errno);
-+ return(-errno);
-+ }
-+ waitpid(pid, NULL, 0);
-+
-+ cmsg = CMSG_FIRSTHDR(&msg);
-+ if(cmsg == NULL){
-+ printk("tuntap_open_tramp : didn't receive a message\n");
-+ return(-EINVAL);
-+ }
-+ if((cmsg->cmsg_level != SOL_SOCKET) ||
-+ (cmsg->cmsg_type != SCM_RIGHTS)){
-+ printk("tuntap_open_tramp : didn't receive a descriptor\n");
-+ return(-EINVAL);
-+ }
-+ *fd_out = ((int *) CMSG_DATA(cmsg))[0];
-+ return(0);
-+}
-+
-+static int tuntap_open(void *data)
-+{
-+ struct ifreq ifr;
-+ struct tuntap_data *pri = data;
-+ char *output, *buffer;
-+ int err, fds[2], len, used;
-+
-+ err = tap_open_common(pri->dev, pri->gate_addr);
-+ if(err < 0)
-+ return(err);
-+
-+ if(pri->fixed_config){
-+ pri->fd = os_open_file("/dev/net/tun", of_rdwr(OPENFLAGS()), 0);
-+ if(pri->fd < 0){
-+ printk("Failed to open /dev/net/tun, err = %d\n",
-+ -pri->fd);
-+ return(pri->fd);
-+ }
-+ memset(&ifr, 0, sizeof(ifr));
-+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
-+ strncpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name) - 1);
-+ if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){
-+ printk("TUNSETIFF failed, errno = %d\n", errno);
-+ os_close_file(pri->fd);
-+ return(-errno);
-+ }
-+ }
-+ else {
-+ err = os_pipe(fds, 0, 0);
-+ if(err < 0){
-+ printk("tuntap_open : os_pipe failed - err = %d\n",
-+ -err);
-+ return(err);
-+ }
-+
-+ buffer = get_output_buffer(&len);
-+ if(buffer != NULL) len--;
-+ used = 0;
-+
-+ err = tuntap_open_tramp(pri->gate_addr, &pri->fd, fds[0],
-+ fds[1], buffer, len, &used);
-+
-+ output = buffer;
-+ if(err < 0) {
-+ printk("%s", output);
-+ free_output_buffer(buffer);
-+ printk("tuntap_open_tramp failed - err = %d\n", -err);
-+ return(err);
-+ }
-+
-+ pri->dev_name = uml_strdup(buffer);
-+ output += IFNAMSIZ;
-+ printk("%s", output);
-+ free_output_buffer(buffer);
-+
-+ os_close_file(fds[0]);
-+ iter_addresses(pri->dev, open_addr, pri->dev_name);
-+ }
-+
-+ return(pri->fd);
-+}
-+
-+static void tuntap_close(int fd, void *data)
-+{
-+ struct tuntap_data *pri = data;
-+
-+ if(!pri->fixed_config)
-+ iter_addresses(pri->dev, close_addr, pri->dev_name);
-+ os_close_file(fd);
-+ pri->fd = -1;
-+}
-+
-+static int tuntap_set_mtu(int mtu, void *data)
-+{
-+ return(mtu);
-+}
-+
-+struct net_user_info tuntap_user_info = {
-+ .init = tuntap_user_init,
-+ .open = tuntap_open,
-+ .close = tuntap_close,
-+ .remove = NULL,
-+ .set_mtu = tuntap_set_mtu,
-+ .add_address = tuntap_add_addr,
-+ .delete_address = tuntap_del_addr,
-+ .max_packet = MAX_PACKET
-+};
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/os-Linux/file.c um/arch/um/os-Linux/file.c
---- orig/arch/um/os-Linux/file.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/os-Linux/file.c 2004-01-10 06:52:24.000000000 -0500
-@@ -0,0 +1,668 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdio.h>
-+#include <unistd.h>
-+#include <errno.h>
-+#include <fcntl.h>
-+#include <signal.h>
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <sys/socket.h>
-+#include <sys/un.h>
-+#include <sys/ioctl.h>
-+#include <sys/mount.h>
-+#include <sys/uio.h>
-+#include "os.h"
-+#include "user.h"
-+#include "kern_util.h"
-+
-+static void copy_stat(struct uml_stat *dst, struct stat64 *src)
-+{
-+ *dst = ((struct uml_stat) {
-+ .ust_dev = src->st_dev, /* device */
-+ .ust_ino = src->st_ino, /* inode */
-+ .ust_mode = src->st_mode, /* protection */
-+ .ust_nlink = src->st_nlink, /* number of hard links */
-+ .ust_uid = src->st_uid, /* user ID of owner */
-+ .ust_gid = src->st_gid, /* group ID of owner */
-+ .ust_size = src->st_size, /* total size, in bytes */
-+ .ust_blksize = src->st_blksize, /* blocksize for filesys I/O */
-+ .ust_blocks = src->st_blocks, /* number of blocks allocated */
-+ .ust_atime = src->st_atime, /* time of last access */
-+ .ust_mtime = src->st_mtime, /* time of last modification */
-+ .ust_ctime = src->st_ctime, /* time of last change */
-+ });
-+}
-+
-+int os_stat_fd(const int fd, struct uml_stat *ubuf)
-+{
-+ struct stat64 sbuf;
-+ int err;
-+
-+ do {
-+ err = fstat64(fd, &sbuf);
-+ } while((err < 0) && (errno == EINTR)) ;
-+
-+ if(err < 0)
-+ return(-errno);
-+
-+ if(ubuf != NULL)
-+ copy_stat(ubuf, &sbuf);
-+ return(err);
-+}
-+
-+int os_stat_file(const char *file_name, struct uml_stat *ubuf)
-+{
-+ struct stat64 sbuf;
-+ int err;
-+
-+ do {
-+ err = stat64(file_name, &sbuf);
-+ } while((err < 0) && (errno == EINTR)) ;
-+
-+ if(err < 0)
-+ return(-errno);
-+
-+ if(ubuf != NULL)
-+ copy_stat(ubuf, &sbuf);
-+ return(err);
-+}
-+
-+int os_access(const char* file, int mode)
-+{
-+ int amode, err;
-+
-+ amode=(mode&OS_ACC_R_OK ? R_OK : 0) | (mode&OS_ACC_W_OK ? W_OK : 0) |
-+ (mode&OS_ACC_X_OK ? X_OK : 0) | (mode&OS_ACC_F_OK ? F_OK : 0) ;
-+
-+ err = access(file, amode);
-+ if(err < 0)
-+ return(-errno);
-+
-+ return(0);
-+}
-+
-+void os_print_error(int error, const char* str)
-+{
-+ errno = error < 0 ? -error : error;
-+
-+ perror(str);
-+}
-+
-+/* FIXME? required only by hostaudio (because it passes ioctls verbatim) */
-+int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
-+{
-+ int err;
-+
-+ err = ioctl(fd, cmd, arg);
-+ if(err < 0)
-+ return(-errno);
-+
-+ return(err);
-+}
-+
-+int os_window_size(int fd, int *rows, int *cols)
-+{
-+ struct winsize size;
-+
-+ if(ioctl(fd, TIOCGWINSZ, &size) < 0)
-+ return(-errno);
-+
-+ *rows = size.ws_row;
-+ *cols = size.ws_col;
-+
-+ return(0);
-+}
-+
-+int os_new_tty_pgrp(int fd, int pid)
-+{
-+ if(ioctl(fd, TIOCSCTTY, 0) < 0){
-+ printk("TIOCSCTTY failed, errno = %d\n", errno);
-+ return(-errno);
-+ }
-+
-+ if(tcsetpgrp(fd, pid) < 0){
-+ printk("tcsetpgrp failed, errno = %d\n", errno);
-+ return(-errno);
-+ }
-+
-+ return(0);
-+}
-+
-+/* FIXME: ensure namebuf in os_get_if_name is big enough */
-+int os_get_ifname(int fd, char* namebuf)
-+{
-+ if(ioctl(fd, SIOCGIFNAME, namebuf) < 0)
-+ return(-errno);
-+
-+ return(0);
-+}
-+
-+int os_set_slip(int fd)
-+{
-+ int disc, sencap;
-+
-+ disc = N_SLIP;
-+ if(ioctl(fd, TIOCSETD, &disc) < 0){
-+ printk("Failed to set slip line discipline - "
-+ "errno = %d\n", errno);
-+ return(-errno);
-+ }
-+
-+ sencap = 0;
-+ if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0){
-+ printk("Failed to set slip encapsulation - "
-+ "errno = %d\n", errno);
-+ return(-errno);
-+ }
-+
-+ return(0);
-+}
-+
-+int os_set_owner(int fd, int pid)
-+{
-+ if(fcntl(fd, F_SETOWN, pid) < 0){
-+ int save_errno = errno;
-+
-+ if(fcntl(fd, F_GETOWN, 0) != pid)
-+ return(-save_errno);
-+ }
-+
-+ return(0);
-+}
-+
-+/* FIXME? moved wholesale from sigio_user.c to get fcntls out of that file */
-+int os_sigio_async(int master, int slave)
-+{
-+ int flags;
-+
-+ flags = fcntl(master, F_GETFL);
-+ if(flags < 0) {
-+ printk("fcntl F_GETFL failed, errno = %d\n", errno);
-+ return(-errno);
-+ }
-+
-+ if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
-+ (fcntl(master, F_SETOWN, os_getpid()) < 0)){
-+ printk("fcntl F_SETFL or F_SETOWN failed, errno = %d\n", errno);
-+ return(-errno);
-+ }
-+
-+ if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)){
-+ printk("fcntl F_SETFL failed, errno = %d\n", errno);
-+ return(-errno);
-+ }
-+
-+ return(0);
-+}
-+
-+int os_mode_fd(int fd, int mode)
-+{
-+ int err;
-+
-+ do {
-+ err = fchmod(fd, mode);
-+ } while((err < 0) && (errno==EINTR)) ;
-+
-+ if(err < 0)
-+ return(-errno);
-+
-+ return(0);
-+}
-+
-+int os_file_type(char *file)
-+{
-+ struct uml_stat buf;
-+ int err;
-+
-+ err = os_stat_file(file, &buf);
-+ if(err < 0)
-+ return(err);
-+
-+ if(S_ISDIR(buf.ust_mode)) return(OS_TYPE_DIR);
-+ else if(S_ISLNK(buf.ust_mode)) return(OS_TYPE_SYMLINK);
-+ else if(S_ISCHR(buf.ust_mode)) return(OS_TYPE_CHARDEV);
-+ else if(S_ISBLK(buf.ust_mode)) return(OS_TYPE_BLOCKDEV);
-+ else if(S_ISFIFO(buf.ust_mode)) return(OS_TYPE_FIFO);
-+ else if(S_ISSOCK(buf.ust_mode)) return(OS_TYPE_SOCK);
-+ else return(OS_TYPE_FILE);
-+}
-+
-+int os_file_mode(char *file, struct openflags *mode_out)
-+{
-+ int err;
-+
-+ *mode_out = OPENFLAGS();
-+
-+ err = os_access(file, OS_ACC_W_OK);
-+ if((err < 0) && (err != -EACCES))
-+ return(err);
-+
-+ *mode_out = of_write(*mode_out);
-+
-+ err = os_access(file, OS_ACC_R_OK);
-+ if((err < 0) && (err != -EACCES))
-+ return(err);
-+
-+ *mode_out = of_read(*mode_out);
-+
-+ return(0);
-+}
-+
-+int os_open_file(char *file, struct openflags flags, int mode)
-+{
-+ int fd, f = 0;
-+
-+ if(flags.r && flags.w) f = O_RDWR;
-+ else if(flags.r) f = O_RDONLY;
-+ else if(flags.w) f = O_WRONLY;
-+ else f = 0;
-+
-+ if(flags.s) f |= O_SYNC;
-+ if(flags.c) f |= O_CREAT;
-+ if(flags.t) f |= O_TRUNC;
-+ if(flags.e) f |= O_EXCL;
-+
-+ fd = open64(file, f, mode);
-+ if(fd < 0)
-+ return(-errno);
-+
-+ if(flags.cl && fcntl(fd, F_SETFD, 1)){
-+ os_close_file(fd);
-+ return(-errno);
-+ }
-+
-+ return(fd);
-+}
-+
-+int os_connect_socket(char *name)
-+{
-+ struct sockaddr_un sock;
-+ int fd, err;
-+
-+ sock.sun_family = AF_UNIX;
-+ snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name);
-+
-+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
-+ if(fd < 0)
-+ return(fd);
-+
-+ err = connect(fd, (struct sockaddr *) &sock, sizeof(sock));
-+ if(err)
-+ return(-errno);
-+
-+ return(fd);
-+}
-+
-+void os_close_file(int fd)
-+{
-+ close(fd);
-+}
-+
-+int os_seek_file(int fd, __u64 offset)
-+{
-+ __u64 actual;
-+
-+ actual = lseek64(fd, offset, SEEK_SET);
-+ if(actual != offset) return(-errno);
-+ return(0);
-+}
-+
-+static int fault_buffer(void *start, int len,
-+ int (*copy_proc)(void *addr, void *buf, int len))
-+{
-+ int page = getpagesize(), i;
-+ char c;
-+
-+ for(i = 0; i < len; i += page){
-+ if((*copy_proc)(start + i, &c, sizeof(c)))
-+ return(-EFAULT);
-+ }
-+ if((len % page) != 0){
-+ if((*copy_proc)(start + len - 1, &c, sizeof(c)))
-+ return(-EFAULT);
-+ }
-+ return(0);
-+}
-+
-+static int file_io(int fd, void *buf, int len,
-+ int (*io_proc)(int fd, void *buf, int len),
-+ int (*copy_user_proc)(void *addr, void *buf, int len))
-+{
-+ int n, err;
-+
-+ do {
-+ n = (*io_proc)(fd, buf, len);
-+ if((n < 0) && (errno == EFAULT)){
-+ err = fault_buffer(buf, len, copy_user_proc);
-+ if(err)
-+ return(err);
-+ n = (*io_proc)(fd, buf, len);
-+ }
-+ } while((n < 0) && (errno == EINTR));
-+
-+ if(n < 0)
-+ return(-errno);
-+ return(n);
-+}
-+
-+int os_read_file(int fd, void *buf, int len)
-+{
-+ return(file_io(fd, buf, len, (int (*)(int, void *, int)) read,
-+ copy_from_user_proc));
-+}
-+
-+int os_write_file(int fd, const void *buf, int len)
-+{
-+ return(file_io(fd, (void *) buf, len,
-+ (int (*)(int, void *, int)) write, copy_to_user_proc));
-+}
-+
-+int os_file_size(char *file, long long *size_out)
-+{
-+ struct uml_stat buf;
-+ int err;
-+
-+ err = os_stat_file(file, &buf);
-+ if(err < 0){
-+ printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
-+ return(err);
-+ }
-+
-+ if(S_ISBLK(buf.ust_mode)){
-+ int fd, blocks;
-+
-+ fd = os_open_file(file, of_read(OPENFLAGS()), 0);
-+ if(fd < 0){
-+ printk("Couldn't open \"%s\", errno = %d\n", file, -fd);
-+ return(fd);
-+ }
-+ if(ioctl(fd, BLKGETSIZE, &blocks) < 0){
-+ printk("Couldn't get the block size of \"%s\", "
-+ "errno = %d\n", file, errno);
-+ err = -errno;
-+ os_close_file(fd);
-+ return(err);
-+ }
-+ *size_out = ((long long) blocks) * 512;
-+ os_close_file(fd);
-+ return(0);
-+ }
-+ *size_out = buf.ust_size;
-+ return(0);
-+}
-+
-+int os_file_modtime(char *file, unsigned long *modtime)
-+{
-+ struct uml_stat buf;
-+ int err;
-+
-+ err = os_stat_file(file, &buf);
-+ if(err < 0){
-+ printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
-+ return(err);
-+ }
-+
-+ *modtime = buf.ust_mtime;
-+ return(0);
-+}
-+
-+int os_get_exec_close(int fd, int* close_on_exec)
-+{
-+ int ret;
-+
-+ do {
-+ ret = fcntl(fd, F_GETFD);
-+ } while((ret < 0) && (errno == EINTR)) ;
-+
-+ if(ret < 0)
-+ return(-errno);
-+
-+ *close_on_exec = (ret&FD_CLOEXEC) ? 1 : 0;
-+ return(ret);
-+}
-+
-+int os_set_exec_close(int fd, int close_on_exec)
-+{
-+ int flag, err;
-+
-+ if(close_on_exec) flag = FD_CLOEXEC;
-+ else flag = 0;
-+
-+ do {
-+ err = fcntl(fd, F_SETFD, flag);
-+ } while((err < 0) && (errno == EINTR)) ;
-+
-+ if(err < 0)
-+ return(-errno);
-+ return(err);
-+}
-+
-+int os_pipe(int *fds, int stream, int close_on_exec)
-+{
-+ int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
-+
-+ err = socketpair(AF_UNIX, type, 0, fds);
-+ if(err < 0)
-+ return(-errno);
-+
-+ if(!close_on_exec)
-+ return(0);
-+
-+ err = os_set_exec_close(fds[0], 1);
-+ if(err < 0)
-+ goto error;
-+
-+ err = os_set_exec_close(fds[1], 1);
-+ if(err < 0)
-+ goto error;
-+
-+ return(0);
-+
-+ error:
-+ printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err);
-+ os_close_file(fds[1]);
-+ os_close_file(fds[0]);
-+ return(err);
-+}
-+
-+int os_set_fd_async(int fd, int owner)
-+{
-+ /* XXX This should do F_GETFL first */
-+ if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){
-+ printk("os_set_fd_async : failed to set O_ASYNC and "
-+ "O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
-+ return(-errno);
-+ }
-+#ifdef notdef
-+ if(fcntl(fd, F_SETFD, 1) < 0){
-+ printk("os_set_fd_async : Setting FD_CLOEXEC failed, "
-+ "errno = %d\n", errno);
-+ }
-+#endif
-+
-+ if((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
-+ (fcntl(fd, F_SETOWN, owner) < 0)){
-+ printk("os_set_fd_async : Failed to fcntl F_SETOWN "
-+ "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd,
-+ owner, errno);
-+ return(-errno);
-+ }
-+
-+ return(0);
-+}
-+
-+int os_set_fd_block(int fd, int blocking)
-+{
-+ int flags;
-+
-+ flags = fcntl(fd, F_GETFL);
-+
-+ if(blocking) flags &= ~O_NONBLOCK;
-+ else flags |= O_NONBLOCK;
-+
-+ if(fcntl(fd, F_SETFL, flags) < 0){
-+ printk("Failed to change blocking on fd # %d, errno = %d\n",
-+ fd, errno);
-+ return(-errno);
-+ }
-+ return(0);
-+}
-+
-+int os_accept_connection(int fd)
-+{
-+ int new;
-+
-+ new = accept(fd, NULL, 0);
-+ if(new < 0)
-+ return(-errno);
-+ return(new);
-+}
-+
-+#ifndef SHUT_RD
-+#define SHUT_RD 0
-+#endif
-+
-+#ifndef SHUT_WR
-+#define SHUT_WR 1
-+#endif
-+
-+#ifndef SHUT_RDWR
-+#define SHUT_RDWR 2
-+#endif
-+
-+int os_shutdown_socket(int fd, int r, int w)
-+{
-+ int what, err;
-+
-+ if(r && w) what = SHUT_RDWR;
-+ else if(r) what = SHUT_RD;
-+ else if(w) what = SHUT_WR;
-+ else {
-+ printk("os_shutdown_socket : neither r or w was set\n");
-+ return(-EINVAL);
-+ }
-+ err = shutdown(fd, what);
-+ if(err < 0)
-+ return(-errno);
-+ return(0);
-+}
-+
-+int os_rcv_fd(int fd, int *helper_pid_out)
-+{
-+ int new, n;
-+ char buf[CMSG_SPACE(sizeof(new))];
-+ struct msghdr msg;
-+ struct cmsghdr *cmsg;
-+ struct iovec iov;
-+
-+ msg.msg_name = NULL;
-+ msg.msg_namelen = 0;
-+ iov = ((struct iovec) { .iov_base = helper_pid_out,
-+ .iov_len = sizeof(*helper_pid_out) });
-+ msg.msg_iov = &iov;
-+ msg.msg_iovlen = 1;
-+ msg.msg_control = buf;
-+ msg.msg_controllen = sizeof(buf);
-+ msg.msg_flags = 0;
-+
-+ n = recvmsg(fd, &msg, 0);
-+ if(n < 0)
-+ return(-errno);
-+
-+ else if(n != sizeof(iov.iov_len))
-+ *helper_pid_out = -1;
-+
-+ cmsg = CMSG_FIRSTHDR(&msg);
-+ if(cmsg == NULL){
-+ printk("rcv_fd didn't receive anything, error = %d\n", errno);
-+ return(-1);
-+ }
-+ if((cmsg->cmsg_level != SOL_SOCKET) ||
-+ (cmsg->cmsg_type != SCM_RIGHTS)){
-+ printk("rcv_fd didn't receive a descriptor\n");
-+ return(-1);
-+ }
-+
-+ new = ((int *) CMSG_DATA(cmsg))[0];
-+ return(new);
-+}
-+
-+int os_create_unix_socket(char *file, int len, int close_on_exec)
-+{
-+ struct sockaddr_un addr;
-+ int sock, err;
-+
-+ sock = socket(PF_UNIX, SOCK_DGRAM, 0);
-+ if (sock < 0){
-+ printk("create_unix_socket - socket failed, errno = %d\n",
-+ errno);
-+ return(-errno);
-+ }
-+
-+ if(close_on_exec) {
-+ err = os_set_exec_close(sock, 1);
-+ if(err < 0)
-+ printk("create_unix_socket : close_on_exec failed, "
-+ "err = %d", -err);
-+ }
-+
-+ addr.sun_family = AF_UNIX;
-+
-+ /* XXX Be more careful about overflow */
-+ snprintf(addr.sun_path, len, "%s", file);
-+
-+ err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
-+ if (err < 0){
-+ printk("create_listening_socket at '%s' - bind failed, "
-+ "errno = %d\n", file, errno);
-+ return(-errno);
-+ }
-+
-+ return(sock);
-+}
-+
-+void os_flush_stdout(void)
-+{
-+ fflush(stdout);
-+}
-+
-+int os_lock_file(int fd, int excl)
-+{
-+ int type = excl ? F_WRLCK : F_RDLCK;
-+ struct flock lock = ((struct flock) { .l_type = type,
-+ .l_whence = SEEK_SET,
-+ .l_start = 0,
-+ .l_len = 0 } );
-+ int err, save;
-+
-+ err = fcntl(fd, F_SETLK, &lock);
-+ if(!err)
-+ goto out;
-+
-+ save = -errno;
-+ err = fcntl(fd, F_GETLK, &lock);
-+ if(err){
-+ err = -errno;
-+ goto out;
-+ }
-+
-+ printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid);
-+ err = save;
-+ out:
-+ return(err);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/os-Linux/include/file.h um/arch/um/os-Linux/include/file.h
---- orig/arch/um/os-Linux/include/file.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/os-Linux/include/file.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,22 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __OS_FILE_H__
-+#define __OS_FILE_H__
-+
-+#define DEV_NULL "/dev/null"
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/os-Linux/Makefile um/arch/um/os-Linux/Makefile
---- orig/arch/um/os-Linux/Makefile 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/os-Linux/Makefile 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,17 @@
-+#
-+# Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+# Licensed under the GPL
-+#
-+
-+O_TARGET = built-in.o
-+
-+obj-y = file.o process.o tty.o
-+
-+include $(TOPDIR)/Rules.make
-+
-+$(obj-y) : %.o: %.c
-+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $<
-+
-+clean :
-+
-+archmrproper:
-diff -Naur -X ../exclude-files orig/arch/um/os-Linux/process.c um/arch/um/os-Linux/process.c
---- orig/arch/um/os-Linux/process.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/os-Linux/process.c 2004-01-10 06:53:44.000000000 -0500
-@@ -0,0 +1,148 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@addtoit.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <unistd.h>
-+#include <stdio.h>
-+#include <errno.h>
-+#include <signal.h>
-+#include <sys/mman.h>
-+#include <sys/wait.h>
-+#include "os.h"
-+#include "user.h"
-+
-+#define ARBITRARY_ADDR -1
-+#define FAILURE_PID -1
-+
-+unsigned long os_process_pc(int pid)
-+{
-+ char proc_stat[sizeof("/proc/#####/stat\0")], buf[256];
-+ unsigned long pc;
-+ int fd, err;
-+
-+ sprintf(proc_stat, "/proc/%d/stat", pid);
-+ fd = os_open_file(proc_stat, of_read(OPENFLAGS()), 0);
-+ if(fd < 0){
-+ printk("os_process_pc - couldn't open '%s', err = %d\n",
-+ proc_stat, -fd);
-+ return(ARBITRARY_ADDR);
-+ }
-+ err = os_read_file(fd, buf, sizeof(buf));
-+ if(err < 0){
-+ printk("os_process_pc - couldn't read '%s', err = %d\n",
-+ proc_stat, -err);
-+ os_close_file(fd);
-+ return(ARBITRARY_ADDR);
-+ }
-+ os_close_file(fd);
-+ pc = ARBITRARY_ADDR;
-+ if(sscanf(buf, "%*d %*s %*c %*d %*d %*d %*d %*d %*d %*d %*d "
-+ "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
-+ "%*d %*d %*d %*d %ld", &pc) != 1){
-+ printk("os_process_pc - couldn't find pc in '%s'\n", buf);
-+ }
-+ return(pc);
-+}
-+
-+int os_process_parent(int pid)
-+{
-+ char stat[sizeof("/proc/nnnnn/stat\0")];
-+ char data[256];
-+ int parent, n, fd;
-+
-+ if(pid == -1) return(-1);
-+
-+ snprintf(stat, sizeof(stat), "/proc/%d/stat", pid);
-+ fd = os_open_file(stat, of_read(OPENFLAGS()), 0);
-+ if(fd < 0){
-+ printk("Couldn't open '%s', err = %d\n", stat, -fd);
-+ return(FAILURE_PID);
-+ }
-+
-+ n = os_read_file(fd, data, sizeof(data));
-+ os_close_file(fd);
-+
-+ if(n < 0){
-+ printk("Couldn't read '%s', err = %d\n", stat, -n);
-+ return(FAILURE_PID);
-+ }
-+
-+ parent = FAILURE_PID;
-+ /* XXX This will break if there is a space in the command */
-+ n = sscanf(data, "%*d %*s %*c %d", &parent);
-+ if(n != 1)
-+ printk("Failed to scan '%s'\n", data);
-+
-+ return(parent);
-+}
-+
-+void os_stop_process(int pid)
-+{
-+ kill(pid, SIGSTOP);
-+}
-+
-+void os_kill_process(int pid, int reap_child)
-+{
-+ kill(pid, SIGKILL);
-+ if(reap_child)
-+ waitpid(pid, NULL, 0);
-+
-+}
-+
-+void os_usr1_process(int pid)
-+{
-+ kill(pid, SIGUSR1);
-+}
-+
-+int os_getpid(void)
-+{
-+ return(getpid());
-+}
-+
-+int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len,
-+ int r, int w, int x)
-+{
-+ void *loc;
-+ int prot;
-+
-+ prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
-+ (x ? PROT_EXEC : 0);
-+
-+ loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED,
-+ fd, off);
-+ if(loc == MAP_FAILED)
-+ return(-errno);
-+ return(0);
-+}
-+
-+int os_protect_memory(void *addr, unsigned long len, int r, int w, int x)
-+{
-+ int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
-+ (x ? PROT_EXEC : 0));
-+
-+ if(mprotect(addr, len, prot) < 0)
-+ return(-errno);
-+ return(0);
-+}
-+
-+int os_unmap_memory(void *addr, int len)
-+{
-+ int err;
-+
-+ err = munmap(addr, len);
-+ if(err < 0)
-+ return(-errno);
-+ return(0);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/os-Linux/tty.c um/arch/um/os-Linux/tty.c
---- orig/arch/um/os-Linux/tty.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/os-Linux/tty.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,61 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdlib.h>
-+#include <errno.h>
-+#include "os.h"
-+#include "user.h"
-+#include "kern_util.h"
-+
-+struct grantpt_info {
-+ int fd;
-+ int res;
-+ int err;
-+};
-+
-+static void grantpt_cb(void *arg)
-+{
-+ struct grantpt_info *info = arg;
-+
-+ info->res = grantpt(info->fd);
-+ info->err = errno;
-+}
-+
-+int get_pty(void)
-+{
-+ struct grantpt_info info;
-+ int fd;
-+
-+ fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0);
-+ if(fd < 0){
-+ printk("get_pty : Couldn't open /dev/ptmx - err = %d\n", -fd);
-+ return(fd);
-+ }
-+
-+ info.fd = fd;
-+ initial_thread_cb(grantpt_cb, &info);
-+
-+ if(info.res < 0){
-+ printk("get_pty : Couldn't grant pty - errno = %d\n",
-+ -info.err);
-+ return(-1);
-+ }
-+ if(unlockpt(fd) < 0){
-+ printk("get_pty : Couldn't unlock pty - errno = %d\n", errno);
-+ return(-1);
-+ }
-+ return(fd);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/sys-i386/bugs.c um/arch/um/sys-i386/bugs.c
---- orig/arch/um/sys-i386/bugs.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-i386/bugs.c 2004-01-21 22:42:39.000000000 -0500
-@@ -0,0 +1,222 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <unistd.h>
-+#include <errno.h>
-+#include <string.h>
-+#include <sys/signal.h>
-+#include <asm/ldt.h>
-+#include "kern_util.h"
-+#include "user.h"
-+#include "sysdep/ptrace.h"
-+#include "task.h"
-+#include "os.h"
-+
-+#define MAXTOKEN 64
-+
-+/* Set during early boot */
-+int host_has_cmov = 1;
-+int host_has_xmm = 0;
-+
-+static char token(int fd, char *buf, int len, char stop)
-+{
-+ int n;
-+ char *ptr, *end, c;
-+
-+ ptr = buf;
-+ end = &buf[len];
-+ do {
-+ n = os_read_file(fd, ptr, sizeof(*ptr));
-+ c = *ptr++;
-+ if(n != sizeof(*ptr)){
-+ if(n == 0) return(0);
-+ printk("Reading /proc/cpuinfo failed, err = %d\n", -n);
-+ if(n < 0)
-+ return(n);
-+ else
-+ return(-EIO);
-+ }
-+ } while((c != '\n') && (c != stop) && (ptr < end));
-+
-+ if(ptr == end){
-+ printk("Failed to find '%c' in /proc/cpuinfo\n", stop);
-+ return(-1);
-+ }
-+ *(ptr - 1) = '\0';
-+ return(c);
-+}
-+
-+static int find_cpuinfo_line(int fd, char *key, char *scratch, int len)
-+{
-+ int n;
-+ char c;
-+
-+ scratch[len - 1] = '\0';
-+ while(1){
-+ c = token(fd, scratch, len - 1, ':');
-+ if(c <= 0)
-+ return(0);
-+ else if(c != ':'){
-+ printk("Failed to find ':' in /proc/cpuinfo\n");
-+ return(0);
-+ }
-+
-+ if(!strncmp(scratch, key, strlen(key)))
-+ return(1);
-+
-+ do {
-+ n = os_read_file(fd, &c, sizeof(c));
-+ if(n != sizeof(c)){
-+ printk("Failed to find newline in "
-+ "/proc/cpuinfo, err = %d\n", -n);
-+ return(0);
-+ }
-+ } while(c != '\n');
-+ }
-+ return(0);
-+}
-+
-+int cpu_feature(char *what, char *buf, int len)
-+{
-+ int fd, ret = 0;
-+
-+ fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
-+ if(fd < 0){
-+ printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd);
-+ return(0);
-+ }
-+
-+ if(!find_cpuinfo_line(fd, what, buf, len)){
-+ printk("Couldn't find '%s' line in /proc/cpuinfo\n", what);
-+ goto out_close;
-+ }
-+
-+ token(fd, buf, len, '\n');
-+ ret = 1;
-+
-+ out_close:
-+ os_close_file(fd);
-+ return(ret);
-+}
-+
-+static int check_cpu_flag(char *feature, int *have_it)
-+{
-+ char buf[MAXTOKEN], c;
-+ int fd, len = sizeof(buf)/sizeof(buf[0]);
-+
-+ printk("Checking for host processor %s support...", feature);
-+ fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
-+ if(fd < 0){
-+ printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd);
-+ return(0);
-+ }
-+
-+ *have_it = 0;
-+ if(!find_cpuinfo_line(fd, "flags", buf, sizeof(buf) / sizeof(buf[0])))
-+ goto out;
-+
-+ c = token(fd, buf, len - 1, ' ');
-+ if(c < 0) goto out;
-+ else if(c != ' '){
-+ printk("Failed to find ' ' in /proc/cpuinfo\n");
-+ goto out;
-+ }
-+
-+ while(1){
-+ c = token(fd, buf, len - 1, ' ');
-+ if(c < 0) goto out;
-+ else if(c == '\n') break;
-+
-+ if(!strcmp(buf, feature)){
-+ *have_it = 1;
-+ goto out;
-+ }
-+ }
-+ out:
-+ if(*have_it == 0) printk("No\n");
-+ else if(*have_it == 1) printk("Yes\n");
-+ os_close_file(fd);
-+ return(1);
-+}
-+
-+#if 0 /* This doesn't work in tt mode, plus it's causing compilation problems
-+ * for some people.
-+ */
-+static void disable_lcall(void)
-+{
-+ struct modify_ldt_ldt_s ldt;
-+ int err;
-+
-+ bzero(&ldt, sizeof(ldt));
-+ ldt.entry_number = 7;
-+ ldt.base_addr = 0;
-+ ldt.limit = 0;
-+ err = modify_ldt(1, &ldt, sizeof(ldt));
-+ if(err)
-+ printk("Failed to disable lcall7 - errno = %d\n", errno);
-+}
-+#endif
-+
-+void arch_init_thread(void)
-+{
-+#if 0
-+ disable_lcall();
-+#endif
-+}
-+
-+void arch_check_bugs(void)
-+{
-+ int have_it;
-+
-+ if(os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0){
-+ printk("/proc/cpuinfo not available - skipping CPU capability "
-+ "checks\n");
-+ return;
-+ }
-+ if(check_cpu_flag("cmov", &have_it))
-+ host_has_cmov = have_it;
-+ if(check_cpu_flag("xmm", &have_it))
-+ host_has_xmm = have_it;
-+}
-+
-+int arch_handle_signal(int sig, union uml_pt_regs *regs)
-+{
-+ unsigned char tmp[2];
-+
-+ /* This is testing for a cmov (0x0f 0x4x) instruction causing a
-+ * SIGILL in init.
-+ */
-+ if((sig != SIGILL) || (TASK_PID(get_current()) != 1)) return(0);
-+
-+ if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2))
-+ panic("SIGILL in init, could not read instructions!\n");
-+ if((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40))
-+ return(0);
-+
-+ if(host_has_cmov == 0)
-+ panic("SIGILL caused by cmov, which this processor doesn't "
-+ "implement, boot a filesystem compiled for older "
-+ "processors");
-+ else if(host_has_cmov == 1)
-+ panic("SIGILL caused by cmov, which this processor claims to "
-+ "implement");
-+ else if(host_has_cmov == -1)
-+ panic("SIGILL caused by cmov, couldn't tell if this processor "
-+ "implements it, boot a filesystem compiled for older "
-+ "processors");
-+ else panic("Bad value for host_has_cmov (%d)", host_has_cmov);
-+ return(0);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/sys-i386/checksum.S um/arch/um/sys-i386/checksum.S
---- orig/arch/um/sys-i386/checksum.S 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-i386/checksum.S 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,460 @@
-+/*
-+ * INET An implementation of the TCP/IP protocol suite for the LINUX
-+ * operating system. INET is implemented using the BSD Socket
-+ * interface as the means of communication with the user level.
-+ *
-+ * IP/TCP/UDP checksumming routines
-+ *
-+ * Authors: Jorge Cwik, <jorge@laser.satlink.net>
-+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
-+ * Tom May, <ftom@netcom.com>
-+ * Pentium Pro/II routines:
-+ * Alexander Kjeldaas <astor@guardian.no>
-+ * Finn Arne Gangstad <finnag@guardian.no>
-+ * Lots of code moved from tcp.c and ip.c; see those files
-+ * for more names.
-+ *
-+ * Changes: Ingo Molnar, converted csum_partial_copy() to 2.1 exception
-+ * handling.
-+ * Andi Kleen, add zeroing on error
-+ * converted to pure assembler
-+ *
-+ * 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/config.h>
-+#include <asm/errno.h>
-+
-+/*
-+ * computes a partial checksum, e.g. for TCP/UDP fragments
-+ */
-+
-+/*
-+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
-+ */
-+
-+.text
-+.align 4
-+.globl arch_csum_partial
-+
-+#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
-+
-+ /*
-+ * Experiments with Ethernet and SLIP connections show that buff
-+ * is aligned on either a 2-byte or 4-byte boundary. We get at
-+ * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
-+ * Fortunately, it is easy to convert 2-byte alignment to 4-byte
-+ * alignment for the unrolled loop.
-+ */
-+arch_csum_partial:
-+ pushl %esi
-+ pushl %ebx
-+ movl 20(%esp),%eax # Function arg: unsigned int sum
-+ movl 16(%esp),%ecx # Function arg: int len
-+ movl 12(%esp),%esi # Function arg: unsigned char *buff
-+ testl $2, %esi # Check alignment.
-+ jz 2f # Jump if alignment is ok.
-+ subl $2, %ecx # Alignment uses up two bytes.
-+ jae 1f # Jump if we had at least two bytes.
-+ addl $2, %ecx # ecx was < 2. Deal with it.
-+ jmp 4f
-+1: movw (%esi), %bx
-+ addl $2, %esi
-+ addw %bx, %ax
-+ adcl $0, %eax
-+2:
-+ movl %ecx, %edx
-+ shrl $5, %ecx
-+ jz 2f
-+ testl %esi, %esi
-+1: movl (%esi), %ebx
-+ adcl %ebx, %eax
-+ movl 4(%esi), %ebx
-+ adcl %ebx, %eax
-+ movl 8(%esi), %ebx
-+ adcl %ebx, %eax
-+ movl 12(%esi), %ebx
-+ adcl %ebx, %eax
-+ movl 16(%esi), %ebx
-+ adcl %ebx, %eax
-+ movl 20(%esi), %ebx
-+ adcl %ebx, %eax
-+ movl 24(%esi), %ebx
-+ adcl %ebx, %eax
-+ movl 28(%esi), %ebx
-+ adcl %ebx, %eax
-+ lea 32(%esi), %esi
-+ dec %ecx
-+ jne 1b
-+ adcl $0, %eax
-+2: movl %edx, %ecx
-+ andl $0x1c, %edx
-+ je 4f
-+ shrl $2, %edx # This clears CF
-+3: adcl (%esi), %eax
-+ lea 4(%esi), %esi
-+ dec %edx
-+ jne 3b
-+ adcl $0, %eax
-+4: andl $3, %ecx
-+ jz 7f
-+ cmpl $2, %ecx
-+ jb 5f
-+ movw (%esi),%cx
-+ leal 2(%esi),%esi
-+ je 6f
-+ shll $16,%ecx
-+5: movb (%esi),%cl
-+6: addl %ecx,%eax
-+ adcl $0, %eax
-+7:
-+ popl %ebx
-+ popl %esi
-+ ret
-+
-+#else
-+
-+/* Version for PentiumII/PPro */
-+
-+arch_csum_partial:
-+ pushl %esi
-+ pushl %ebx
-+ movl 20(%esp),%eax # Function arg: unsigned int sum
-+ movl 16(%esp),%ecx # Function arg: int len
-+ movl 12(%esp),%esi # Function arg: const unsigned char *buf
-+
-+ testl $2, %esi
-+ jnz 30f
-+10:
-+ movl %ecx, %edx
-+ movl %ecx, %ebx
-+ andl $0x7c, %ebx
-+ shrl $7, %ecx
-+ addl %ebx,%esi
-+ shrl $2, %ebx
-+ negl %ebx
-+ lea 45f(%ebx,%ebx,2), %ebx
-+ testl %esi, %esi
-+ jmp *%ebx
-+
-+ # Handle 2-byte-aligned regions
-+20: addw (%esi), %ax
-+ lea 2(%esi), %esi
-+ adcl $0, %eax
-+ jmp 10b
-+
-+30: subl $2, %ecx
-+ ja 20b
-+ je 32f
-+ movzbl (%esi),%ebx # csumming 1 byte, 2-aligned
-+ addl %ebx, %eax
-+ adcl $0, %eax
-+ jmp 80f
-+32:
-+ addw (%esi), %ax # csumming 2 bytes, 2-aligned
-+ adcl $0, %eax
-+ jmp 80f
-+
-+40:
-+ addl -128(%esi), %eax
-+ adcl -124(%esi), %eax
-+ adcl -120(%esi), %eax
-+ adcl -116(%esi), %eax
-+ adcl -112(%esi), %eax
-+ adcl -108(%esi), %eax
-+ adcl -104(%esi), %eax
-+ adcl -100(%esi), %eax
-+ adcl -96(%esi), %eax
-+ adcl -92(%esi), %eax
-+ adcl -88(%esi), %eax
-+ adcl -84(%esi), %eax
-+ adcl -80(%esi), %eax
-+ adcl -76(%esi), %eax
-+ adcl -72(%esi), %eax
-+ adcl -68(%esi), %eax
-+ adcl -64(%esi), %eax
-+ adcl -60(%esi), %eax
-+ adcl -56(%esi), %eax
-+ adcl -52(%esi), %eax
-+ adcl -48(%esi), %eax
-+ adcl -44(%esi), %eax
-+ adcl -40(%esi), %eax
-+ adcl -36(%esi), %eax
-+ adcl -32(%esi), %eax
-+ adcl -28(%esi), %eax
-+ adcl -24(%esi), %eax
-+ adcl -20(%esi), %eax
-+ adcl -16(%esi), %eax
-+ adcl -12(%esi), %eax
-+ adcl -8(%esi), %eax
-+ adcl -4(%esi), %eax
-+45:
-+ lea 128(%esi), %esi
-+ adcl $0, %eax
-+ dec %ecx
-+ jge 40b
-+ movl %edx, %ecx
-+50: andl $3, %ecx
-+ jz 80f
-+
-+ # Handle the last 1-3 bytes without jumping
-+ notl %ecx # 1->2, 2->1, 3->0, higher bits are masked
-+ movl $0xffffff,%ebx # by the shll and shrl instructions
-+ shll $3,%ecx
-+ shrl %cl,%ebx
-+ andl -128(%esi),%ebx # esi is 4-aligned so should be ok
-+ addl %ebx,%eax
-+ adcl $0,%eax
-+80:
-+ popl %ebx
-+ popl %esi
-+ ret
-+
-+#endif
-+
-+/*
-+unsigned int csum_partial_copy_generic (const char *src, char *dst,
-+ int len, int sum, int *src_err_ptr, int *dst_err_ptr)
-+ */
-+
-+/*
-+ * Copy from ds while checksumming, otherwise like csum_partial
-+ *
-+ * The macros SRC and DST specify the type of access for the instruction.
-+ * thus we can call a custom exception handler for all access types.
-+ *
-+ * FIXME: could someone double-check whether I haven't mixed up some SRC and
-+ * DST definitions? It's damn hard to trigger all cases. I hope I got
-+ * them all but there's no guarantee.
-+ */
-+
-+#define SRC(y...) \
-+ 9999: y; \
-+ .section __ex_table, "a"; \
-+ .long 9999b, 6001f ; \
-+ .previous
-+
-+#define DST(y...) \
-+ 9999: y; \
-+ .section __ex_table, "a"; \
-+ .long 9999b, 6002f ; \
-+ .previous
-+
-+.align 4
-+.globl csum_partial_copy_generic_i386
-+
-+#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
-+
-+#define ARGBASE 16
-+#define FP 12
-+
-+csum_partial_copy_generic_i386:
-+ subl $4,%esp
-+ pushl %edi
-+ pushl %esi
-+ pushl %ebx
-+ movl ARGBASE+16(%esp),%eax # sum
-+ movl ARGBASE+12(%esp),%ecx # len
-+ movl ARGBASE+4(%esp),%esi # src
-+ movl ARGBASE+8(%esp),%edi # dst
-+
-+ testl $2, %edi # Check alignment.
-+ jz 2f # Jump if alignment is ok.
-+ subl $2, %ecx # Alignment uses up two bytes.
-+ jae 1f # Jump if we had at least two bytes.
-+ addl $2, %ecx # ecx was < 2. Deal with it.
-+ jmp 4f
-+SRC(1: movw (%esi), %bx )
-+ addl $2, %esi
-+DST( movw %bx, (%edi) )
-+ addl $2, %edi
-+ addw %bx, %ax
-+ adcl $0, %eax
-+2:
-+ movl %ecx, FP(%esp)
-+ shrl $5, %ecx
-+ jz 2f
-+ testl %esi, %esi
-+SRC(1: movl (%esi), %ebx )
-+SRC( movl 4(%esi), %edx )
-+ adcl %ebx, %eax
-+DST( movl %ebx, (%edi) )
-+ adcl %edx, %eax
-+DST( movl %edx, 4(%edi) )
-+
-+SRC( movl 8(%esi), %ebx )
-+SRC( movl 12(%esi), %edx )
-+ adcl %ebx, %eax
-+DST( movl %ebx, 8(%edi) )
-+ adcl %edx, %eax
-+DST( movl %edx, 12(%edi) )
-+
-+SRC( movl 16(%esi), %ebx )
-+SRC( movl 20(%esi), %edx )
-+ adcl %ebx, %eax
-+DST( movl %ebx, 16(%edi) )
-+ adcl %edx, %eax
-+DST( movl %edx, 20(%edi) )
-+
-+SRC( movl 24(%esi), %ebx )
-+SRC( movl 28(%esi), %edx )
-+ adcl %ebx, %eax
-+DST( movl %ebx, 24(%edi) )
-+ adcl %edx, %eax
-+DST( movl %edx, 28(%edi) )
-+
-+ lea 32(%esi), %esi
-+ lea 32(%edi), %edi
-+ dec %ecx
-+ jne 1b
-+ adcl $0, %eax
-+2: movl FP(%esp), %edx
-+ movl %edx, %ecx
-+ andl $0x1c, %edx
-+ je 4f
-+ shrl $2, %edx # This clears CF
-+SRC(3: movl (%esi), %ebx )
-+ adcl %ebx, %eax
-+DST( movl %ebx, (%edi) )
-+ lea 4(%esi), %esi
-+ lea 4(%edi), %edi
-+ dec %edx
-+ jne 3b
-+ adcl $0, %eax
-+4: andl $3, %ecx
-+ jz 7f
-+ cmpl $2, %ecx
-+ jb 5f
-+SRC( movw (%esi), %cx )
-+ leal 2(%esi), %esi
-+DST( movw %cx, (%edi) )
-+ leal 2(%edi), %edi
-+ je 6f
-+ shll $16,%ecx
-+SRC(5: movb (%esi), %cl )
-+DST( movb %cl, (%edi) )
-+6: addl %ecx, %eax
-+ adcl $0, %eax
-+7:
-+5000:
-+
-+# Exception handler:
-+.section .fixup, "ax"
-+
-+6001:
-+ movl ARGBASE+20(%esp), %ebx # src_err_ptr
-+ movl $-EFAULT, (%ebx)
-+
-+ # zero the complete destination - computing the rest
-+ # is too much work
-+ movl ARGBASE+8(%esp), %edi # dst
-+ movl ARGBASE+12(%esp), %ecx # len
-+ xorl %eax,%eax
-+ rep ; stosb
-+
-+ jmp 5000b
-+
-+6002:
-+ movl ARGBASE+24(%esp), %ebx # dst_err_ptr
-+ movl $-EFAULT,(%ebx)
-+ jmp 5000b
-+
-+.previous
-+
-+ popl %ebx
-+ popl %esi
-+ popl %edi
-+ popl %ecx # equivalent to addl $4,%esp
-+ ret
-+
-+#else
-+
-+/* Version for PentiumII/PPro */
-+
-+#define ROUND1(x) \
-+ SRC(movl x(%esi), %ebx ) ; \
-+ addl %ebx, %eax ; \
-+ DST(movl %ebx, x(%edi) ) ;
-+
-+#define ROUND(x) \
-+ SRC(movl x(%esi), %ebx ) ; \
-+ adcl %ebx, %eax ; \
-+ DST(movl %ebx, x(%edi) ) ;
-+
-+#define ARGBASE 12
-+
-+csum_partial_copy_generic_i386:
-+ pushl %ebx
-+ pushl %edi
-+ pushl %esi
-+ movl ARGBASE+4(%esp),%esi #src
-+ movl ARGBASE+8(%esp),%edi #dst
-+ movl ARGBASE+12(%esp),%ecx #len
-+ movl ARGBASE+16(%esp),%eax #sum
-+# movl %ecx, %edx
-+ movl %ecx, %ebx
-+ movl %esi, %edx
-+ shrl $6, %ecx
-+ andl $0x3c, %ebx
-+ negl %ebx
-+ subl %ebx, %esi
-+ subl %ebx, %edi
-+ lea -1(%esi),%edx
-+ andl $-32,%edx
-+ lea 3f(%ebx,%ebx), %ebx
-+ testl %esi, %esi
-+ jmp *%ebx
-+1: addl $64,%esi
-+ addl $64,%edi
-+ SRC(movb -32(%edx),%bl) ; SRC(movb (%edx),%bl)
-+ ROUND1(-64) ROUND(-60) ROUND(-56) ROUND(-52)
-+ ROUND (-48) ROUND(-44) ROUND(-40) ROUND(-36)
-+ ROUND (-32) ROUND(-28) ROUND(-24) ROUND(-20)
-+ ROUND (-16) ROUND(-12) ROUND(-8) ROUND(-4)
-+3: adcl $0,%eax
-+ addl $64, %edx
-+ dec %ecx
-+ jge 1b
-+4: movl ARGBASE+12(%esp),%edx #len
-+ andl $3, %edx
-+ jz 7f
-+ cmpl $2, %edx
-+ jb 5f
-+SRC( movw (%esi), %dx )
-+ leal 2(%esi), %esi
-+DST( movw %dx, (%edi) )
-+ leal 2(%edi), %edi
-+ je 6f
-+ shll $16,%edx
-+5:
-+SRC( movb (%esi), %dl )
-+DST( movb %dl, (%edi) )
-+6: addl %edx, %eax
-+ adcl $0, %eax
-+7:
-+.section .fixup, "ax"
-+6001: movl ARGBASE+20(%esp), %ebx # src_err_ptr
-+ movl $-EFAULT, (%ebx)
-+ # zero the complete destination (computing the rest is too much work)
-+ movl ARGBASE+8(%esp),%edi # dst
-+ movl ARGBASE+12(%esp),%ecx # len
-+ xorl %eax,%eax
-+ rep; stosb
-+ jmp 7b
-+6002: movl ARGBASE+24(%esp), %ebx # dst_err_ptr
-+ movl $-EFAULT, (%ebx)
-+ jmp 7b
-+.previous
-+
-+ popl %esi
-+ popl %edi
-+ popl %ebx
-+ ret
-+
-+#undef ROUND
-+#undef ROUND1
-+
-+#endif
-diff -Naur -X ../exclude-files orig/arch/um/sys-i386/fault.c um/arch/um/sys-i386/fault.c
---- orig/arch/um/sys-i386/fault.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-i386/fault.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,34 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <signal.h>
-+#include "sysdep/ptrace.h"
-+#include "sysdep/sigcontext.h"
-+
-+extern unsigned long search_exception_table(unsigned long addr);
-+
-+int arch_fixup(unsigned long address, void *sc_ptr)
-+{
-+ struct sigcontext *sc = sc_ptr;
-+ unsigned long fixup;
-+
-+ fixup = search_exception_table(address);
-+ if(fixup != 0){
-+ sc->eip = fixup;
-+ return(1);
-+ }
-+ return(0);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/sys-i386/ksyms.c um/arch/um/sys-i386/ksyms.c
---- orig/arch/um/sys-i386/ksyms.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-i386/ksyms.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,17 @@
-+#include "linux/module.h"
-+#include "linux/in6.h"
-+#include "linux/rwsem.h"
-+#include "asm/byteorder.h"
-+#include "asm/semaphore.h"
-+#include "asm/uaccess.h"
-+#include "asm/checksum.h"
-+#include "asm/errno.h"
-+
-+EXPORT_SYMBOL(__down_failed);
-+EXPORT_SYMBOL(__down_failed_interruptible);
-+EXPORT_SYMBOL(__down_failed_trylock);
-+EXPORT_SYMBOL(__up_wakeup);
-+
-+/* Networking helper routines. */
-+EXPORT_SYMBOL(csum_partial_copy_from);
-+EXPORT_SYMBOL(csum_partial_copy_to);
-diff -Naur -X ../exclude-files orig/arch/um/sys-i386/ldt.c um/arch/um/sys-i386/ldt.c
---- orig/arch/um/sys-i386/ldt.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-i386/ldt.c 2004-01-19 04:01:11.000000000 -0500
-@@ -0,0 +1,94 @@
-+/*
-+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/config.h"
-+#include "linux/slab.h"
-+#include "asm/uaccess.h"
-+#include "asm/ptrace.h"
-+#include "choose-mode.h"
-+#include "kern.h"
-+
-+#ifdef CONFIG_MODE_TT
-+extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
-+
-+/* XXX this needs copy_to_user and copy_from_user */
-+
-+int sys_modify_ldt_tt(int func, void *ptr, unsigned long bytecount)
-+{
-+ if(verify_area(VERIFY_READ, ptr, bytecount)) return(-EFAULT);
-+ return(modify_ldt(func, ptr, bytecount));
-+}
-+#endif
-+
-+#ifdef CONFIG_MODE_SKAS
-+extern int userspace_pid;
-+
-+int sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount)
-+{
-+ struct ptrace_ldt ldt;
-+ void *buf;
-+ int res, n;
-+
-+ buf = kmalloc(bytecount, GFP_KERNEL);
-+ if(buf == NULL)
-+ return(-ENOMEM);
-+
-+ res = 0;
-+
-+ switch(func){
-+ case 1:
-+ case 0x11:
-+ res = copy_from_user(buf, ptr, bytecount);
-+ break;
-+ }
-+
-+ if(res != 0){
-+ res = -EFAULT;
-+ goto out;
-+ }
-+
-+ ldt = ((struct ptrace_ldt) { .func = func,
-+ .ptr = buf,
-+ .bytecount = bytecount });
-+ res = ptrace(PTRACE_LDT, userspace_pid, 0, (unsigned long) &ldt);
-+ if(res < 0)
-+ goto out;
-+
-+ switch(func){
-+ case 0:
-+ case 2:
-+ n = res;
-+ res = copy_to_user(ptr, buf, n);
-+ if(res != 0)
-+ res = -EFAULT;
-+ else
-+ res = n;
-+ break;
-+ }
-+
-+ out:
-+ kfree(buf);
-+ return(res);
-+}
-+#endif
-+
-+int sys_modify_ldt(int func, void *ptr, unsigned long bytecount)
-+{
-+ return(CHOOSE_MODE_PROC(sys_modify_ldt_tt, sys_modify_ldt_skas, func,
-+ ptr, bytecount));
-+}
-+
-+
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/sys-i386/Makefile um/arch/um/sys-i386/Makefile
---- orig/arch/um/sys-i386/Makefile 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-i386/Makefile 2003-11-09 11:55:24.000000000 -0500
-@@ -0,0 +1,46 @@
-+#
-+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+# Licensed under the GPL
-+#
-+
-+O_TARGET = built-in.o
-+
-+obj-y = bugs.o checksum.o extable.o fault.o ksyms.o ldt.o ptrace.o \
-+ ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o time.o
-+export-objs = ksyms.o
-+
-+USER_OBJS = bugs.o ptrace_user.o sigcontext.o fault.o
-+
-+SYMLINKS = semaphore.c extable.c
-+
-+semaphore.c-dir = kernel
-+extable.c-dir = mm
-+
-+include $(TOPDIR)/Rules.make
-+
-+$(USER_OBJS) : %.o: %.c
-+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $<
-+
-+define make_link
-+ -rm -f $1
-+ ln -sf $(TOPDIR)/arch/i386/$($1-dir)/$1 $1
-+endef
-+
-+$(SYMLINKS):
-+ $(call make_link,$@)
-+
-+clean:
-+ $(MAKE) -C util clean
-+ rm -f $(SYMLINKS)
-+
-+fastdep:
-+
-+dep:
-+
-+archmrproper:
-+
-+archclean:
-+
-+archdep:
-+
-+modules:
-diff -Naur -X ../exclude-files orig/arch/um/sys-i386/ptrace.c um/arch/um/sys-i386/ptrace.c
---- orig/arch/um/sys-i386/ptrace.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-i386/ptrace.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,365 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/sched.h"
-+#include "asm/elf.h"
-+#include "asm/ptrace.h"
-+#include "asm/uaccess.h"
-+#include "ptrace_user.h"
-+#include "sysdep/sigcontext.h"
-+#include "sysdep/sc.h"
-+
-+void arch_switch(void)
-+{
-+ update_debugregs(current->thread.arch.debugregs_seq);
-+}
-+
-+int is_syscall(unsigned long addr)
-+{
-+ unsigned short instr;
-+ int n;
-+
-+ n = copy_from_user(&instr, (void *) addr, sizeof(instr));
-+ if(n){
-+ printk("is_syscall : failed to read instruction from 0x%lu\n",
-+ addr);
-+ return(0);
-+ }
-+ return(instr == 0x80cd);
-+}
-+
-+/* determines which flags the user has access to. */
-+/* 1 = access 0 = no access */
-+#define FLAG_MASK 0x00044dd5
-+
-+int putreg(struct task_struct *child, int regno, unsigned long value)
-+{
-+ regno >>= 2;
-+ switch (regno) {
-+ case FS:
-+ if (value && (value & 3) != 3)
-+ return -EIO;
-+ PT_REGS_FS(&child->thread.regs) = value;
-+ return 0;
-+ case GS:
-+ if (value && (value & 3) != 3)
-+ return -EIO;
-+ PT_REGS_GS(&child->thread.regs) = value;
-+ return 0;
-+ case DS:
-+ case ES:
-+ if (value && (value & 3) != 3)
-+ return -EIO;
-+ value &= 0xffff;
-+ break;
-+ case SS:
-+ case CS:
-+ if ((value & 3) != 3)
-+ return -EIO;
-+ value &= 0xffff;
-+ break;
-+ case EFL:
-+ value &= FLAG_MASK;
-+ value |= PT_REGS_EFLAGS(&child->thread.regs);
-+ break;
-+ }
-+ PT_REGS_SET(&child->thread.regs, regno, value);
-+ return 0;
-+}
-+
-+unsigned long getreg(struct task_struct *child, int regno)
-+{
-+ unsigned long retval = ~0UL;
-+
-+ regno >>= 2;
-+ switch (regno) {
-+ case FS:
-+ case GS:
-+ case DS:
-+ case ES:
-+ case SS:
-+ case CS:
-+ retval = 0xffff;
-+ /* fall through */
-+ default:
-+ retval &= PT_REG(&child->thread.regs, regno);
-+ }
-+ return retval;
-+}
-+
-+struct i387_fxsave_struct {
-+ unsigned short cwd;
-+ unsigned short swd;
-+ unsigned short twd;
-+ unsigned short fop;
-+ long fip;
-+ long fcs;
-+ long foo;
-+ long fos;
-+ long mxcsr;
-+ long reserved;
-+ long st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */
-+ long xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */
-+ long padding[56];
-+};
-+
-+/*
-+ * FPU tag word conversions.
-+ */
-+
-+static inline unsigned short twd_i387_to_fxsr( unsigned short twd )
-+{
-+ unsigned int tmp; /* to avoid 16 bit prefixes in the code */
-+
-+ /* Transform each pair of bits into 01 (valid) or 00 (empty) */
-+ tmp = ~twd;
-+ tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
-+ /* and move the valid bits to the lower byte. */
-+ tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
-+ tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
-+ tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
-+ return tmp;
-+}
-+
-+static inline unsigned long twd_fxsr_to_i387( struct i387_fxsave_struct *fxsave )
-+{
-+ struct _fpxreg *st = NULL;
-+ unsigned long twd = (unsigned long) fxsave->twd;
-+ unsigned long tag;
-+ unsigned long ret = 0xffff0000;
-+ int i;
-+
-+#define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16);
-+
-+ for ( i = 0 ; i < 8 ; i++ ) {
-+ if ( twd & 0x1 ) {
-+ st = (struct _fpxreg *) FPREG_ADDR( fxsave, i );
-+
-+ switch ( st->exponent & 0x7fff ) {
-+ case 0x7fff:
-+ tag = 2; /* Special */
-+ break;
-+ case 0x0000:
-+ if ( !st->significand[0] &&
-+ !st->significand[1] &&
-+ !st->significand[2] &&
-+ !st->significand[3] ) {
-+ tag = 1; /* Zero */
-+ } else {
-+ tag = 2; /* Special */
-+ }
-+ break;
-+ default:
-+ if ( st->significand[3] & 0x8000 ) {
-+ tag = 0; /* Valid */
-+ } else {
-+ tag = 2; /* Special */
-+ }
-+ break;
-+ }
-+ } else {
-+ tag = 3; /* Empty */
-+ }
-+ ret |= (tag << (2 * i));
-+ twd = twd >> 1;
-+ }
-+ return ret;
-+}
-+
-+/*
-+ * FXSR floating point environment conversions.
-+ */
-+
-+#ifdef CONFIG_MODE_TT
-+static inline int convert_fxsr_to_user_tt(struct _fpstate *buf,
-+ struct pt_regs *regs)
-+{
-+ struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs));
-+ unsigned long env[7];
-+ struct _fpreg *to;
-+ struct _fpxreg *from;
-+ int i;
-+
-+ env[0] = (unsigned long)fxsave->cwd | 0xffff0000;
-+ env[1] = (unsigned long)fxsave->swd | 0xffff0000;
-+ env[2] = twd_fxsr_to_i387(fxsave);
-+ env[3] = fxsave->fip;
-+ env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16);
-+ env[5] = fxsave->foo;
-+ env[6] = fxsave->fos;
-+
-+ if ( __copy_to_user( buf, env, 7 * sizeof(unsigned long) ) )
-+ return 1;
-+
-+ to = &buf->_st[0];
-+ from = (struct _fpxreg *) &fxsave->st_space[0];
-+ for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
-+ if ( __copy_to_user( to, from, sizeof(*to) ) )
-+ return 1;
-+ }
-+ return 0;
-+}
-+#endif
-+
-+static inline int convert_fxsr_to_user(struct _fpstate *buf,
-+ struct pt_regs *regs)
-+{
-+ return(CHOOSE_MODE(convert_fxsr_to_user_tt(buf, regs), 0));
-+}
-+
-+#ifdef CONFIG_MODE_TT
-+static inline int convert_fxsr_from_user_tt(struct pt_regs *regs,
-+ struct _fpstate *buf)
-+{
-+ struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs));
-+ unsigned long env[7];
-+ struct _fpxreg *to;
-+ struct _fpreg *from;
-+ int i;
-+
-+ if ( __copy_from_user( env, buf, 7 * sizeof(long) ) )
-+ return 1;
-+
-+ fxsave->cwd = (unsigned short)(env[0] & 0xffff);
-+ fxsave->swd = (unsigned short)(env[1] & 0xffff);
-+ fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff));
-+ fxsave->fip = env[3];
-+ fxsave->fop = (unsigned short)((env[4] & 0xffff0000) >> 16);
-+ fxsave->fcs = (env[4] & 0xffff);
-+ fxsave->foo = env[5];
-+ fxsave->fos = env[6];
-+
-+ to = (struct _fpxreg *) &fxsave->st_space[0];
-+ from = &buf->_st[0];
-+ for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
-+ if ( __copy_from_user( to, from, sizeof(*from) ) )
-+ return 1;
-+ }
-+ return 0;
-+}
-+#endif
-+
-+static inline int convert_fxsr_from_user(struct pt_regs *regs,
-+ struct _fpstate *buf)
-+{
-+ return(CHOOSE_MODE(convert_fxsr_from_user_tt(regs, buf), 0));
-+}
-+
-+int get_fpregs(unsigned long buf, struct task_struct *child)
-+{
-+ int err;
-+
-+ err = convert_fxsr_to_user((struct _fpstate *) buf,
-+ &child->thread.regs);
-+ if(err) return(-EFAULT);
-+ else return(0);
-+}
-+
-+int set_fpregs(unsigned long buf, struct task_struct *child)
-+{
-+ int err;
-+
-+ err = convert_fxsr_from_user(&child->thread.regs,
-+ (struct _fpstate *) buf);
-+ if(err) return(-EFAULT);
-+ else return(0);
-+}
-+
-+#ifdef CONFIG_MODE_TT
-+int get_fpxregs_tt(unsigned long buf, struct task_struct *tsk)
-+{
-+ struct pt_regs *regs = &tsk->thread.regs;
-+ struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs));
-+ int err;
-+
-+ err = __copy_to_user((void *) buf, fxsave,
-+ sizeof(struct user_fxsr_struct));
-+ if(err) return -EFAULT;
-+ else return 0;
-+}
-+#endif
-+
-+int get_fpxregs(unsigned long buf, struct task_struct *tsk)
-+{
-+ return(CHOOSE_MODE(get_fpxregs_tt(buf, tsk), 0));
-+}
-+
-+#ifdef CONFIG_MODE_TT
-+int set_fpxregs_tt(unsigned long buf, struct task_struct *tsk)
-+{
-+ struct pt_regs *regs = &tsk->thread.regs;
-+ struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs));
-+ int err;
-+
-+ err = __copy_from_user(fxsave, (void *) buf,
-+ sizeof(struct user_fxsr_struct) );
-+ if(err) return -EFAULT;
-+ else return 0;
-+}
-+#endif
-+
-+int set_fpxregs(unsigned long buf, struct task_struct *tsk)
-+{
-+ return(CHOOSE_MODE(set_fpxregs_tt(buf, tsk), 0));
-+}
-+
-+#ifdef notdef
-+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
-+{
-+ fpu->cwd = (((SC_FP_CW(PT_REGS_SC(regs)) & 0xffff) << 16) |
-+ (SC_FP_SW(PT_REGS_SC(regs)) & 0xffff));
-+ fpu->swd = SC_FP_CSSEL(PT_REGS_SC(regs)) & 0xffff;
-+ fpu->twd = SC_FP_IPOFF(PT_REGS_SC(regs));
-+ fpu->fip = SC_FP_CSSEL(PT_REGS_SC(regs)) & 0xffff;
-+ fpu->fcs = SC_FP_DATAOFF(PT_REGS_SC(regs));
-+ fpu->foo = SC_FP_DATASEL(PT_REGS_SC(regs));
-+ fpu->fos = 0;
-+ memcpy(fpu->st_space, (void *) SC_FP_ST(PT_REGS_SC(regs)),
-+ sizeof(fpu->st_space));
-+ return(1);
-+}
-+#endif
-+
-+#ifdef CONFIG_MODE_TT
-+static inline void copy_fpu_fxsave_tt(struct pt_regs *regs,
-+ struct user_i387_struct *buf)
-+{
-+ struct i387_fxsave_struct *fpu = SC_FXSR_ENV(PT_REGS_SC(regs));
-+ unsigned short *to;
-+ unsigned short *from;
-+ int i;
-+
-+ memcpy( buf, fpu, 7 * sizeof(long) );
-+
-+ to = (unsigned short *) &buf->st_space[0];
-+ from = (unsigned short *) &fpu->st_space[0];
-+ for ( i = 0 ; i < 8 ; i++, to += 5, from += 8 ) {
-+ memcpy( to, from, 5 * sizeof(unsigned short) );
-+ }
-+}
-+#endif
-+
-+static inline void copy_fpu_fxsave(struct pt_regs *regs,
-+ struct user_i387_struct *buf)
-+{
-+ (void) CHOOSE_MODE(copy_fpu_fxsave_tt(regs, buf), 0);
-+}
-+
-+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu )
-+{
-+ copy_fpu_fxsave(regs, (struct user_i387_struct *) fpu);
-+ return(1);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/sys-i386/ptrace_user.c um/arch/um/sys-i386/ptrace_user.c
---- orig/arch/um/sys-i386/ptrace_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-i386/ptrace_user.c 2003-12-17 01:33:17.000000000 -0500
-@@ -0,0 +1,117 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stdio.h>
-+#include <errno.h>
-+#include <unistd.h>
-+#include <linux/stddef.h>
-+#include <sys/ptrace.h>
-+#include <asm/ptrace.h>
-+#include <asm/user.h>
-+#include "kern_util.h"
-+#include "sysdep/thread.h"
-+#include "user.h"
-+#include "os.h"
-+
-+int ptrace_getregs(long pid, unsigned long *regs_out)
-+{
-+ return(ptrace(PTRACE_GETREGS, pid, 0, regs_out));
-+}
-+
-+int ptrace_setregs(long pid, unsigned long *regs)
-+{
-+ return(ptrace(PTRACE_SETREGS, pid, 0, regs));
-+}
-+
-+int ptrace_getfpregs(long pid, unsigned long *regs)
-+{
-+ return(ptrace(PTRACE_GETFPREGS, pid, 0, regs));
-+}
-+
-+static void write_debugregs(int pid, unsigned long *regs)
-+{
-+ struct user *dummy;
-+ int nregs, i;
-+
-+ dummy = NULL;
-+ nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]);
-+ for(i = 0; i < nregs; i++){
-+ if((i == 4) || (i == 5)) continue;
-+ if(ptrace(PTRACE_POKEUSER, pid, &dummy->u_debugreg[i],
-+ regs[i]) < 0)
-+ printk("write_debugregs - ptrace failed on "
-+ "register %d, errno = %d\n", errno);
-+ }
-+}
-+
-+static void read_debugregs(int pid, unsigned long *regs)
-+{
-+ struct user *dummy;
-+ int nregs, i;
-+
-+ dummy = NULL;
-+ nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]);
-+ for(i = 0; i < nregs; i++){
-+ regs[i] = ptrace(PTRACE_PEEKUSER, pid,
-+ &dummy->u_debugreg[i], 0);
-+ }
-+}
-+
-+/* Accessed only by the tracing thread */
-+static unsigned long kernel_debugregs[8] = { [ 0 ... 7 ] = 0 };
-+static int debugregs_seq = 0;
-+
-+void arch_enter_kernel(void *task, int pid)
-+{
-+ read_debugregs(pid, TASK_DEBUGREGS(task));
-+ write_debugregs(pid, kernel_debugregs);
-+}
-+
-+void arch_leave_kernel(void *task, int pid)
-+{
-+ read_debugregs(pid, kernel_debugregs);
-+ write_debugregs(pid, TASK_DEBUGREGS(task));
-+}
-+
-+void ptrace_pokeuser(unsigned long addr, unsigned long data)
-+{
-+ if((addr < offsetof(struct user, u_debugreg[0])) ||
-+ (addr > offsetof(struct user, u_debugreg[7])))
-+ return;
-+ addr -= offsetof(struct user, u_debugreg[0]);
-+ addr = addr >> 2;
-+ if(kernel_debugregs[addr] == data) return;
-+
-+ kernel_debugregs[addr] = data;
-+ debugregs_seq++;
-+}
-+
-+static void update_debugregs_cb(void *arg)
-+{
-+ int pid = *((int *) arg);
-+
-+ write_debugregs(pid, kernel_debugregs);
-+}
-+
-+void update_debugregs(int seq)
-+{
-+ int me;
-+
-+ if(seq == debugregs_seq) return;
-+
-+ me = os_getpid();
-+ initial_thread_cb(update_debugregs_cb, &me);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/sys-i386/sigcontext.c um/arch/um/sys-i386/sigcontext.c
---- orig/arch/um/sys-i386/sigcontext.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-i386/sigcontext.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,80 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include <stddef.h>
-+#include <string.h>
-+#include <asm/ptrace.h>
-+#include <asm/sigcontext.h>
-+#include "sysdep/ptrace.h"
-+#include "kern_util.h"
-+#include "frame_user.h"
-+
-+int sc_size(void *data)
-+{
-+ struct arch_frame_data *arch = data;
-+
-+ return(sizeof(struct sigcontext) + arch->fpstate_size);
-+}
-+
-+void sc_to_sc(void *to_ptr, void *from_ptr)
-+{
-+ struct sigcontext *to = to_ptr, *from = from_ptr;
-+ int size = sizeof(*to) + signal_frame_sc.common.arch.fpstate_size;
-+
-+ memcpy(to, from, size);
-+ if(from->fpstate != NULL) to->fpstate = (struct _fpstate *) (to + 1);
-+}
-+
-+unsigned long *sc_sigmask(void *sc_ptr)
-+{
-+ struct sigcontext *sc = sc_ptr;
-+
-+ return(&sc->oldmask);
-+}
-+
-+int sc_get_fpregs(unsigned long buf, void *sc_ptr)
-+{
-+ struct sigcontext *sc = sc_ptr;
-+ struct _fpstate *from = sc->fpstate, *to = (struct _fpstate *) buf;
-+ int err = 0;
-+
-+ if(from == NULL){
-+ err |= clear_user_proc(&to->cw, sizeof(to->cw));
-+ err |= clear_user_proc(&to->sw, sizeof(to->sw));
-+ err |= clear_user_proc(&to->tag, sizeof(to->tag));
-+ err |= clear_user_proc(&to->ipoff, sizeof(to->ipoff));
-+ err |= clear_user_proc(&to->cssel, sizeof(to->cssel));
-+ err |= clear_user_proc(&to->dataoff, sizeof(to->dataoff));
-+ err |= clear_user_proc(&to->datasel, sizeof(to->datasel));
-+ err |= clear_user_proc(&to->_st, sizeof(to->_st));
-+ }
-+ else {
-+ err |= copy_to_user_proc(&to->cw, &from->cw, sizeof(to->cw));
-+ err |= copy_to_user_proc(&to->sw, &from->sw, sizeof(to->sw));
-+ err |= copy_to_user_proc(&to->tag, &from->tag,
-+ sizeof(to->tag));
-+ err |= copy_to_user_proc(&to->ipoff, &from->ipoff,
-+ sizeof(to->ipoff));
-+ err |= copy_to_user_proc(&to->cssel,& from->cssel,
-+ sizeof(to->cssel));
-+ err |= copy_to_user_proc(&to->dataoff, &from->dataoff,
-+ sizeof(to->dataoff));
-+ err |= copy_to_user_proc(&to->datasel, &from->datasel,
-+ sizeof(to->datasel));
-+ err |= copy_to_user_proc(to->_st, from->_st, sizeof(to->_st));
-+ }
-+ return(err);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/sys-i386/syscalls.c um/arch/um/sys-i386/syscalls.c
---- orig/arch/um/sys-i386/syscalls.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-i386/syscalls.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,68 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "asm/mman.h"
-+#include "asm/uaccess.h"
-+#include "asm/unistd.h"
-+
-+/*
-+ * Perform the select(nd, in, out, ex, tv) and mmap() system
-+ * calls. Linux/i386 didn't use to be able to handle more than
-+ * 4 system call parameters, so these system calls used a memory
-+ * block for parameter passing..
-+ */
-+
-+struct mmap_arg_struct {
-+ unsigned long addr;
-+ unsigned long len;
-+ unsigned long prot;
-+ unsigned long flags;
-+ unsigned long fd;
-+ unsigned long offset;
-+};
-+
-+extern int old_mmap(unsigned long addr, unsigned long len,
-+ unsigned long prot, unsigned long flags,
-+ unsigned long fd, unsigned long offset);
-+
-+int old_mmap_i386(struct mmap_arg_struct *arg)
-+{
-+ struct mmap_arg_struct a;
-+ int err = -EFAULT;
-+
-+ if (copy_from_user(&a, arg, sizeof(a)))
-+ goto out;
-+
-+ err = old_mmap(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
-+ out:
-+ return err;
-+}
-+
-+struct sel_arg_struct {
-+ unsigned long n;
-+ fd_set *inp, *outp, *exp;
-+ struct timeval *tvp;
-+};
-+
-+int old_select(struct sel_arg_struct *arg)
-+{
-+ struct sel_arg_struct a;
-+
-+ if (copy_from_user(&a, arg, sizeof(a)))
-+ return -EFAULT;
-+ /* sys_select() does the appropriate kernel locking */
-+ return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/sys-i386/sysrq.c um/arch/um/sys-i386/sysrq.c
---- orig/arch/um/sys-i386/sysrq.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-i386/sysrq.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,30 @@
-+#include "linux/kernel.h"
-+#include "linux/smp.h"
-+#include "linux/sched.h"
-+#include "asm/ptrace.h"
-+#include "sysrq.h"
-+
-+void show_regs(struct pt_regs *regs)
-+{
-+ printk("\n");
-+ printk("EIP: %04lx:[<%08lx>] CPU: %d %s",
-+ 0xffff & PT_REGS_CS(regs), PT_REGS_IP(regs),
-+ smp_processor_id(), print_tainted());
-+ if (PT_REGS_CS(regs) & 3)
-+ printk(" ESP: %04lx:%08lx", 0xffff & PT_REGS_SS(regs),
-+ PT_REGS_SP(regs));
-+ printk(" EFLAGS: %08lx\n %s\n", PT_REGS_EFLAGS(regs),
-+ print_tainted());
-+ printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
-+ PT_REGS_EAX(regs), PT_REGS_EBX(regs),
-+ PT_REGS_ECX(regs),
-+ PT_REGS_EDX(regs));
-+ printk("ESI: %08lx EDI: %08lx EBP: %08lx",
-+ PT_REGS_ESI(regs), PT_REGS_EDI(regs),
-+ PT_REGS_EBP(regs));
-+ printk(" DS: %04lx ES: %04lx\n",
-+ 0xffff & PT_REGS_DS(regs),
-+ 0xffff & PT_REGS_ES(regs));
-+
-+ show_trace((unsigned long *) ®s);
-+}
-diff -Naur -X ../exclude-files orig/arch/um/sys-i386/time.c um/arch/um/sys-i386/time.c
---- orig/arch/um/sys-i386/time.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-i386/time.c 2003-11-10 01:46:49.000000000 -0500
-@@ -0,0 +1,24 @@
-+/*
-+ * sys-i386/time.c
-+ * Created 25.9.2002 Sapan Bhatia
-+ *
-+ */
-+
-+unsigned long long time_stamp(void)
-+{
-+ unsigned long low, high;
-+
-+ asm("rdtsc" : "=a" (low), "=d" (high));
-+ return((((unsigned long long) high) << 32) + low);
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/sys-i386/util/Makefile um/arch/um/sys-i386/util/Makefile
---- orig/arch/um/sys-i386/util/Makefile 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-i386/util/Makefile 2003-11-08 08:26:40.000000000 -0500
-@@ -0,0 +1,28 @@
-+EXE = mk_sc mk_thread
-+
-+include $(TOPDIR)/Rules.make
-+
-+all : $(EXE)
-+
-+mk_sc : mk_sc.o
-+ $(HOSTCC) -o mk_sc mk_sc.o
-+
-+mk_sc.o : mk_sc.c
-+ $(HOSTCC) -c $<
-+
-+mk_thread : mk_thread_user.o mk_thread_kern.o
-+ $(HOSTCC) -o mk_thread mk_thread_user.o mk_thread_kern.o
-+
-+mk_thread_user.o : mk_thread_user.c
-+ $(HOSTCC) -c $<
-+
-+mk_thread_kern.o : mk_thread_kern.c
-+ $(HOSTCC) $(CFLAGS) -c $<
-+
-+clean :
-+ $(RM) $(EXE) *.o
-+
-+archmrproper : clean
-+
-+fastdep :
-+
-diff -Naur -X ../exclude-files orig/arch/um/sys-i386/util/mk_sc.c um/arch/um/sys-i386/util/mk_sc.c
---- orig/arch/um/sys-i386/util/mk_sc.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-i386/util/mk_sc.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,52 @@
-+#include <stdio.h>
-+#include <signal.h>
-+#include <linux/stddef.h>
-+
-+#define SC_OFFSET(name, field) \
-+ printf("#define " name "(sc) *((unsigned long *) &(((char *) (sc))[%d]))\n",\
-+ offsetof(struct sigcontext, field))
-+
-+#define SC_FP_OFFSET(name, field) \
-+ printf("#define " name \
-+ "(sc) *((unsigned long *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\
-+ offsetof(struct _fpstate, field))
-+
-+#define SC_FP_OFFSET_PTR(name, field, type) \
-+ printf("#define " name \
-+ "(sc) ((" type " *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\
-+ offsetof(struct _fpstate, field))
-+
-+int main(int argc, char **argv)
-+{
-+ SC_OFFSET("SC_IP", eip);
-+ SC_OFFSET("SC_SP", esp);
-+ SC_OFFSET("SC_FS", fs);
-+ SC_OFFSET("SC_GS", gs);
-+ SC_OFFSET("SC_DS", ds);
-+ SC_OFFSET("SC_ES", es);
-+ SC_OFFSET("SC_SS", ss);
-+ SC_OFFSET("SC_CS", cs);
-+ SC_OFFSET("SC_EFLAGS", eflags);
-+ SC_OFFSET("SC_EAX", eax);
-+ SC_OFFSET("SC_EBX", ebx);
-+ SC_OFFSET("SC_ECX", ecx);
-+ SC_OFFSET("SC_EDX", edx);
-+ SC_OFFSET("SC_EDI", edi);
-+ SC_OFFSET("SC_ESI", esi);
-+ SC_OFFSET("SC_EBP", ebp);
-+ SC_OFFSET("SC_TRAPNO", trapno);
-+ SC_OFFSET("SC_ERR", err);
-+ SC_OFFSET("SC_CR2", cr2);
-+ SC_OFFSET("SC_FPSTATE", fpstate);
-+ SC_OFFSET("SC_SIGMASK", oldmask);
-+ SC_FP_OFFSET("SC_FP_CW", cw);
-+ SC_FP_OFFSET("SC_FP_SW", sw);
-+ SC_FP_OFFSET("SC_FP_TAG", tag);
-+ SC_FP_OFFSET("SC_FP_IPOFF", ipoff);
-+ SC_FP_OFFSET("SC_FP_CSSEL", cssel);
-+ SC_FP_OFFSET("SC_FP_DATAOFF", dataoff);
-+ SC_FP_OFFSET("SC_FP_DATASEL", datasel);
-+ SC_FP_OFFSET_PTR("SC_FP_ST", _st, "struct _fpstate");
-+ SC_FP_OFFSET_PTR("SC_FXSR_ENV", _fxsr_env, "void");
-+ return(0);
-+}
-diff -Naur -X ../exclude-files orig/arch/um/sys-i386/util/mk_thread_kern.c um/arch/um/sys-i386/util/mk_thread_kern.c
---- orig/arch/um/sys-i386/util/mk_thread_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-i386/util/mk_thread_kern.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,22 @@
-+#include "linux/config.h"
-+#include "linux/stddef.h"
-+#include "linux/sched.h"
-+
-+extern void print_head(void);
-+extern void print_constant_ptr(char *name, int value);
-+extern void print_constant(char *name, char *type, int value);
-+extern void print_tail(void);
-+
-+#define THREAD_OFFSET(field) offsetof(struct task_struct, thread.field)
-+
-+int main(int argc, char **argv)
-+{
-+ print_head();
-+ print_constant_ptr("TASK_DEBUGREGS", THREAD_OFFSET(arch.debugregs));
-+#ifdef CONFIG_MODE_TT
-+ print_constant("TASK_EXTERN_PID", "int", THREAD_OFFSET(mode.tt.extern_pid));
-+#endif
-+ print_tail();
-+ return(0);
-+}
-+
-diff -Naur -X ../exclude-files orig/arch/um/sys-i386/util/mk_thread_user.c um/arch/um/sys-i386/util/mk_thread_user.c
---- orig/arch/um/sys-i386/util/mk_thread_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-i386/util/mk_thread_user.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,30 @@
-+#include <stdio.h>
-+
-+void print_head(void)
-+{
-+ printf("/*\n");
-+ printf(" * Generated by mk_thread\n");
-+ printf(" */\n");
-+ printf("\n");
-+ printf("#ifndef __UM_THREAD_H\n");
-+ printf("#define __UM_THREAD_H\n");
-+ printf("\n");
-+}
-+
-+void print_constant_ptr(char *name, int value)
-+{
-+ printf("#define %s(task) ((unsigned long *) "
-+ "&(((char *) (task))[%d]))\n", name, value);
-+}
-+
-+void print_constant(char *name, char *type, int value)
-+{
-+ printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type,
-+ value);
-+}
-+
-+void print_tail(void)
-+{
-+ printf("\n");
-+ printf("#endif\n");
-+}
-diff -Naur -X ../exclude-files orig/arch/um/sys-ia64/Makefile um/arch/um/sys-ia64/Makefile
---- orig/arch/um/sys-ia64/Makefile 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-ia64/Makefile 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,26 @@
-+OBJ = sys.o
-+
-+OBJS =
-+
-+all: $(OBJ)
-+
-+$(OBJ): $(OBJS)
-+ rm -f $@
-+ $(LD) $(LINKFLAGS) --start-group $^ --end-group -o $@
-+clean:
-+ rm -f $(OBJS)
-+
-+fastdep:
-+
-+archmrproper:
-+
-+archclean:
-+ rm -f link.ld
-+ @$(MAKEBOOT) clean
-+
-+archdep:
-+ @$(MAKEBOOT) dep
-+
-+modules:
-+
-+include $(TOPDIR)/Rules.make
-diff -Naur -X ../exclude-files orig/arch/um/sys-ppc/Makefile um/arch/um/sys-ppc/Makefile
---- orig/arch/um/sys-ppc/Makefile 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-ppc/Makefile 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,80 @@
-+OBJ = sys.o
-+
-+.S.o:
-+ $(CC) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
-+
-+OBJS = ptrace.o sigcontext.o semaphore.o checksum.o miscthings.o misc.o \
-+ ptrace_user.o sysrq.o
-+
-+EXTRA_AFLAGS := -DCONFIG_ALL_PPC -I. -I$(TOPDIR)/arch/ppc/kernel
-+
-+all: $(OBJ)
-+
-+$(OBJ): $(OBJS)
-+ rm -f $@
-+ $(LD) $(LINKFLAGS) --start-group $^ --end-group -o $@
-+
-+ptrace_user.o: ptrace_user.c
-+ $(CC) -D__KERNEL__ $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
-+
-+sigcontext.o: sigcontext.c
-+ $(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
-+
-+semaphore.c:
-+ rm -f $@
-+ ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@
-+
-+checksum.S:
-+ rm -f $@
-+ ln -s $(TOPDIR)/arch/ppc/lib/$@ $@
-+
-+mk_defs.c:
-+ rm -f $@
-+ ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@
-+
-+ppc_defs.head:
-+ rm -f $@
-+ ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@
-+
-+ppc_defs.h: mk_defs.c ppc_defs.head \
-+ $(TOPDIR)/include/asm-ppc/mmu.h \
-+ $(TOPDIR)/include/asm-ppc/processor.h \
-+ $(TOPDIR)/include/asm-ppc/pgtable.h \
-+ $(TOPDIR)/include/asm-ppc/ptrace.h
-+# $(CC) $(CFLAGS) -S mk_defs.c
-+ cp ppc_defs.head ppc_defs.h
-+# for bk, this way we can write to the file even if it's not checked out
-+ echo '#define THREAD 608' >> ppc_defs.h
-+ echo '#define PT_REGS 8' >> ppc_defs.h
-+ echo '#define CLONE_VM 256' >> ppc_defs.h
-+# chmod u+w ppc_defs.h
-+# grep '^#define' mk_defs.s >> ppc_defs.h
-+# rm mk_defs.s
-+
-+# the asm link is horrible, and breaks the other targets. This is also
-+# not going to work with parallel makes.
-+
-+checksum.o: checksum.S
-+ rm -f asm
-+ ln -s $(TOPDIR)/include/asm-ppc asm
-+ $(CC) $(EXTRA_AFLAGS) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
-+ rm -f asm
-+
-+misc.o: misc.S ppc_defs.h
-+ rm -f asm
-+ ln -s $(TOPDIR)/include/asm-ppc asm
-+ $(CC) $(EXTRA_AFLAGS) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
-+ rm -f asm
-+
-+clean:
-+ rm -f $(OBJS)
-+ rm -f ppc_defs.h
-+ rm -f checksum.S semaphore.c mk_defs.c
-+
-+fastdep:
-+
-+dep:
-+
-+modules:
-+
-+include $(TOPDIR)/Rules.make
-diff -Naur -X ../exclude-files orig/arch/um/sys-ppc/misc.S um/arch/um/sys-ppc/misc.S
---- orig/arch/um/sys-ppc/misc.S 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-ppc/misc.S 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,116 @@
-+/*
-+ * This file contains miscellaneous low-level functions.
-+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
-+ *
-+ * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
-+ * and Paul Mackerras.
-+ *
-+ * A couple of functions stolen from arch/ppc/kernel/misc.S for UML
-+ * by Chris Emerson.
-+ *
-+ * 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/config.h>
-+#include <asm/processor.h>
-+#include "ppc_asm.h"
-+
-+#if defined(CONFIG_4xx) || defined(CONFIG_8xx)
-+#define CACHE_LINE_SIZE 16
-+#define LG_CACHE_LINE_SIZE 4
-+#define MAX_COPY_PREFETCH 1
-+#elif !defined(CONFIG_PPC64BRIDGE)
-+#define CACHE_LINE_SIZE 32
-+#define LG_CACHE_LINE_SIZE 5
-+#define MAX_COPY_PREFETCH 4
-+#else
-+#define CACHE_LINE_SIZE 128
-+#define LG_CACHE_LINE_SIZE 7
-+#define MAX_COPY_PREFETCH 1
-+#endif /* CONFIG_4xx || CONFIG_8xx */
-+
-+ .text
-+
-+/*
-+ * Clear a page using the dcbz instruction, which doesn't cause any
-+ * memory traffic (except to write out any cache lines which get
-+ * displaced). This only works on cacheable memory.
-+ */
-+_GLOBAL(clear_page)
-+ li r0,4096/CACHE_LINE_SIZE
-+ mtctr r0
-+#ifdef CONFIG_8xx
-+ li r4, 0
-+1: stw r4, 0(r3)
-+ stw r4, 4(r3)
-+ stw r4, 8(r3)
-+ stw r4, 12(r3)
-+#else
-+1: dcbz 0,r3
-+#endif
-+ addi r3,r3,CACHE_LINE_SIZE
-+ bdnz 1b
-+ blr
-+
-+/*
-+ * Copy a whole page. We use the dcbz instruction on the destination
-+ * to reduce memory traffic (it eliminates the unnecessary reads of
-+ * the destination into cache). This requires that the destination
-+ * is cacheable.
-+ */
-+#define COPY_16_BYTES \
-+ lwz r6,4(r4); \
-+ lwz r7,8(r4); \
-+ lwz r8,12(r4); \
-+ lwzu r9,16(r4); \
-+ stw r6,4(r3); \
-+ stw r7,8(r3); \
-+ stw r8,12(r3); \
-+ stwu r9,16(r3)
-+
-+_GLOBAL(copy_page)
-+ addi r3,r3,-4
-+ addi r4,r4,-4
-+ li r5,4
-+
-+#ifndef CONFIG_8xx
-+#if MAX_COPY_PREFETCH > 1
-+ li r0,MAX_COPY_PREFETCH
-+ li r11,4
-+ mtctr r0
-+11: dcbt r11,r4
-+ addi r11,r11,CACHE_LINE_SIZE
-+ bdnz 11b
-+#else /* MAX_COPY_PREFETCH == 1 */
-+ dcbt r5,r4
-+ li r11,CACHE_LINE_SIZE+4
-+#endif /* MAX_COPY_PREFETCH */
-+#endif /* CONFIG_8xx */
-+
-+ li r0,4096/CACHE_LINE_SIZE
-+ mtctr r0
-+1:
-+#ifndef CONFIG_8xx
-+ dcbt r11,r4
-+ dcbz r5,r3
-+#endif
-+ COPY_16_BYTES
-+#if CACHE_LINE_SIZE >= 32
-+ COPY_16_BYTES
-+#if CACHE_LINE_SIZE >= 64
-+ COPY_16_BYTES
-+ COPY_16_BYTES
-+#if CACHE_LINE_SIZE >= 128
-+ COPY_16_BYTES
-+ COPY_16_BYTES
-+ COPY_16_BYTES
-+ COPY_16_BYTES
-+#endif
-+#endif
-+#endif
-+ bdnz 1b
-+ blr
-diff -Naur -X ../exclude-files orig/arch/um/sys-ppc/miscthings.c um/arch/um/sys-ppc/miscthings.c
---- orig/arch/um/sys-ppc/miscthings.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-ppc/miscthings.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,53 @@
-+#include "linux/threads.h"
-+#include "linux/stddef.h" // for NULL
-+#include "linux/elf.h" // for AT_NULL
-+
-+/* The following function nicked from arch/ppc/kernel/process.c and
-+ * adapted slightly */
-+/*
-+ * XXX ld.so expects the auxiliary table to start on
-+ * a 16-byte boundary, so we have to find it and
-+ * move it up. :-(
-+ */
-+void shove_aux_table(unsigned long sp)
-+{
-+ int argc;
-+ char *p;
-+ unsigned long e;
-+ unsigned long aux_start, offset;
-+
-+ argc = *(int *)sp;
-+ sp += sizeof(int) + (argc + 1) * sizeof(char *);
-+ /* skip over the environment pointers */
-+ do {
-+ p = *(char **)sp;
-+ sp += sizeof(char *);
-+ } while (p != NULL);
-+ aux_start = sp;
-+ /* skip to the end of the auxiliary table */
-+ do {
-+ e = *(unsigned long *)sp;
-+ sp += 2 * sizeof(unsigned long);
-+ } while (e != AT_NULL);
-+ offset = ((aux_start + 15) & ~15) - aux_start;
-+ if (offset != 0) {
-+ do {
-+ sp -= sizeof(unsigned long);
-+ e = *(unsigned long *)sp;
-+ *(unsigned long *)(sp + offset) = e;
-+ } while (sp > aux_start);
-+ }
-+}
-+/* END stuff taken from arch/ppc/kernel/process.c */
-+
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/sys-ppc/ptrace.c um/arch/um/sys-ppc/ptrace.c
---- orig/arch/um/sys-ppc/ptrace.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-ppc/ptrace.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,28 @@
-+#include "linux/sched.h"
-+#include "asm/ptrace.h"
-+
-+int putreg(struct task_struct *child, unsigned long regno,
-+ unsigned long value)
-+{
-+ child->thread.process_regs.regs[regno >> 2] = value;
-+ return 0;
-+}
-+
-+unsigned long getreg(struct task_struct *child, unsigned long regno)
-+{
-+ unsigned long retval = ~0UL;
-+
-+ retval &= child->thread.process_regs.regs[regno >> 2];
-+ return retval;
-+}
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/sys-ppc/ptrace_user.c um/arch/um/sys-ppc/ptrace_user.c
---- orig/arch/um/sys-ppc/ptrace_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-ppc/ptrace_user.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,40 @@
-+#include <sys/ptrace.h>
-+#include <errno.h>
-+#include <asm/ptrace.h>
-+#include "sysdep/ptrace.h"
-+
-+int ptrace_getregs(long pid, unsigned long *regs_out)
-+{
-+ int i;
-+ for (i=0; i < sizeof(struct sys_pt_regs)/sizeof(PPC_REG); ++i) {
-+ errno = 0;
-+ regs_out->regs[i] = ptrace(PTRACE_PEEKUSER, pid, i*4, 0);
-+ if (errno) {
-+ return -errno;
-+ }
-+ }
-+ return 0;
-+}
-+
-+int ptrace_setregs(long pid, unsigned long *regs_in)
-+{
-+ int i;
-+ for (i=0; i < sizeof(struct sys_pt_regs)/sizeof(PPC_REG); ++i) {
-+ if (i != 34 /* FIXME: PT_ORIG_R3 */ && i <= PT_MQ) {
-+ if (ptrace(PTRACE_POKEUSER, pid, i*4, regs_in->regs[i]) < 0) {
-+ return -errno;
-+ }
-+ }
-+ }
-+ return 0;
-+}
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/sys-ppc/sigcontext.c um/arch/um/sys-ppc/sigcontext.c
---- orig/arch/um/sys-ppc/sigcontext.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-ppc/sigcontext.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,15 @@
-+#include "asm/ptrace.h"
-+#include "asm/sigcontext.h"
-+#include "sysdep/ptrace.h"
-+#include "user_util.h"
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/sys-ppc/sysrq.c um/arch/um/sys-ppc/sysrq.c
---- orig/arch/um/sys-ppc/sysrq.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/sys-ppc/sysrq.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,43 @@
-+/*
-+ * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/kernel.h"
-+#include "linux/smp.h"
-+#include "asm/ptrace.h"
-+#include "sysrq.h"
-+
-+void show_regs(struct pt_regs_subarch *regs)
-+{
-+ printk("\n");
-+ printk("show_regs(): insert regs here.\n");
-+#if 0
-+ printk("\n");
-+ printk("EIP: %04x:[<%08lx>] CPU: %d",0xffff & regs->xcs, regs->eip,
-+ smp_processor_id());
-+ if (regs->xcs & 3)
-+ printk(" ESP: %04x:%08lx",0xffff & regs->xss, regs->esp);
-+ printk(" EFLAGS: %08lx\n", regs->eflags);
-+ printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
-+ regs->eax, regs->ebx, regs->ecx, regs->edx);
-+ printk("ESI: %08lx EDI: %08lx EBP: %08lx",
-+ regs->esi, regs->edi, regs->ebp);
-+ printk(" DS: %04x ES: %04x\n",
-+ 0xffff & regs->xds, 0xffff & regs->xes);
-+#endif
-+
-+ show_trace(®s->gpr[1]);
-+}
-+
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/arch/um/util/Makefile um/arch/um/util/Makefile
---- orig/arch/um/util/Makefile 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/util/Makefile 2003-11-08 02:51:30.000000000 -0500
-@@ -0,0 +1,26 @@
-+ALL = mk_task mk_constants
-+
-+all : $(ALL)
-+
-+mk_task : mk_task_user.o mk_task_kern.o
-+ $(HOSTCC) -o mk_task mk_task_user.o mk_task_kern.o
-+
-+mk_task_user.o : mk_task_user.c
-+ $(HOSTCC) -c $<
-+
-+mk_task_kern.o : mk_task_kern.c
-+ $(HOSTCC) $(CFLAGS) -c $<
-+
-+mk_constants : mk_constants_user.o mk_constants_kern.o
-+ $(HOSTCC) -o mk_constants mk_constants_user.o mk_constants_kern.o
-+
-+mk_constants_user.o : mk_constants_user.c
-+ $(HOSTCC) -c $<
-+
-+mk_constants_kern.o : mk_constants_kern.c
-+ $(HOSTCC) $(CFLAGS) -c $<
-+
-+clean :
-+ $(RM) $(ALL) *.o *~
-+
-+archmrproper : clean
-diff -Naur -X ../exclude-files orig/arch/um/util/mk_constants_kern.c um/arch/um/util/mk_constants_kern.c
---- orig/arch/um/util/mk_constants_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/util/mk_constants_kern.c 2004-01-10 06:54:51.000000000 -0500
-@@ -0,0 +1,25 @@
-+#include "linux/kernel.h"
-+#include "linux/stringify.h"
-+#include "asm/page.h"
-+
-+extern void print_head(void);
-+extern void print_constant_str(char *name, char *value);
-+extern void print_constant_int(char *name, int value);
-+extern void print_tail(void);
-+
-+int main(int argc, char **argv)
-+{
-+ print_head();
-+ print_constant_int("UM_KERN_PAGE_SIZE", PAGE_SIZE);
-+
-+ print_constant_str("UM_KERN_EMERG", KERN_EMERG);
-+ print_constant_str("UM_KERN_ALERT", KERN_ALERT);
-+ print_constant_str("UM_KERN_CRIT", KERN_CRIT);
-+ print_constant_str("UM_KERN_ERR", KERN_ERR);
-+ print_constant_str("UM_KERN_WARNING", KERN_WARNING);
-+ print_constant_str("UM_KERN_NOTICE", KERN_NOTICE);
-+ print_constant_str("UM_KERN_INFO", KERN_INFO);
-+ print_constant_str("UM_KERN_DEBUG", KERN_DEBUG);
-+ print_tail();
-+ return(0);
-+}
-diff -Naur -X ../exclude-files orig/arch/um/util/mk_constants_user.c um/arch/um/util/mk_constants_user.c
---- orig/arch/um/util/mk_constants_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/util/mk_constants_user.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,28 @@
-+#include <stdio.h>
-+
-+void print_head(void)
-+{
-+ printf("/*\n");
-+ printf(" * Generated by mk_constants\n");
-+ printf(" */\n");
-+ printf("\n");
-+ printf("#ifndef __UM_CONSTANTS_H\n");
-+ printf("#define __UM_CONSTANTS_H\n");
-+ printf("\n");
-+}
-+
-+void print_constant_str(char *name, char *value)
-+{
-+ printf("#define %s \"%s\"\n", name, value);
-+}
-+
-+void print_constant_int(char *name, int value)
-+{
-+ printf("#define %s %d\n", name, value);
-+}
-+
-+void print_tail(void)
-+{
-+ printf("\n");
-+ printf("#endif\n");
-+}
-diff -Naur -X ../exclude-files orig/arch/um/util/mk_task_kern.c um/arch/um/util/mk_task_kern.c
---- orig/arch/um/util/mk_task_kern.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/util/mk_task_kern.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,17 @@
-+#include "linux/sched.h"
-+#include "linux/stddef.h"
-+
-+extern void print(char *name, char *type, int offset);
-+extern void print_ptr(char *name, char *type, int offset);
-+extern void print_head(void);
-+extern void print_tail(void);
-+
-+int main(int argc, char **argv)
-+{
-+ print_head();
-+ print_ptr("TASK_REGS", "union uml_pt_regs",
-+ offsetof(struct task_struct, thread.regs));
-+ print("TASK_PID", "int", offsetof(struct task_struct, pid));
-+ print_tail();
-+ return(0);
-+}
-diff -Naur -X ../exclude-files orig/arch/um/util/mk_task_user.c um/arch/um/util/mk_task_user.c
---- orig/arch/um/util/mk_task_user.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/arch/um/util/mk_task_user.c 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,30 @@
-+#include <stdio.h>
-+
-+void print(char *name, char *type, int offset)
-+{
-+ printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type,
-+ offset);
-+}
-+
-+void print_ptr(char *name, char *type, int offset)
-+{
-+ printf("#define %s(task) ((%s *) &(((char *) (task))[%d]))\n", name, type,
-+ offset);
-+}
-+
-+void print_head(void)
-+{
-+ printf("/*\n");
-+ printf(" * Generated by mk_task\n");
-+ printf(" */\n");
-+ printf("\n");
-+ printf("#ifndef __TASK_H\n");
-+ printf("#define __TASK_H\n");
-+ printf("\n");
-+}
-+
-+void print_tail(void)
-+{
-+ printf("\n");
-+ printf("#endif\n");
-+}
-diff -Naur -X ../exclude-files orig/CREDITS um/CREDITS
---- orig/CREDITS 2003-12-16 22:16:23.000000000 -0500
-+++ um/CREDITS 2003-12-16 22:17:22.000000000 -0500
-@@ -434,6 +434,7 @@
- E: lars@nocrew.org
- W: http://lars.nocrew.org/
- D: dsp56k device driver
-+D: ptrace proxy in user mode kernel port
- S: Kopmansg 2
- S: 411 13 Goteborg
- S: Sweden
-@@ -719,7 +720,7 @@
- E: jdike@karaya.com
- W: http://user-mode-linux.sourceforge.net
- D: User mode kernel port
--S: RR1 Box 67C
-+S: 375 Tubbs Hill Rd
- S: Deering NH 03244
- S: USA
-
-diff -Naur -X ../exclude-files orig/Documentation/Configure.help um/Documentation/Configure.help
---- orig/Documentation/Configure.help 2003-12-16 22:16:23.000000000 -0500
-+++ um/Documentation/Configure.help 2003-12-16 22:17:22.000000000 -0500
-@@ -15821,6 +15821,63 @@
- The module will be called speedtch.o. If you want to compile it as
- a module, say M here and read <file:Documentation/modules.txt>.
-
-+Support for /proc/mm
-+CONFIG_PROC_MM
-+ Enables support for address space separation through /proc/mm.
-+ A host kernel needs to have this enabled in order for UML to
-+ run in skas mode. UML kernels do not need to have this option
-+ unless they will host sub-UMLs.
-+
-+ If you don't know what this does just say Y.
-+
-+Separate Kernel Address Space support
-+CONFIG_MODE_SKAS
-+ This option controls whether skas (separate kernel address space)
-+ support is compiled in. If you have applied the skas patch to the
-+ host and enabled support for /proc/mm in the host kernel, then you
-+ certainly want to say Y here (and consider saying N to
-+ CONFIG_MODE_TT). Otherwise, it is safe to say Y. Disabling this
-+ option will shrink the UML binary slightly.
-+
-+Tracing thread support
-+CONFIG_MODE_TT
-+ This option controls whether tracing thread support is compiled
-+ into UML. Normally, this should be set to Y. If you intend to
-+ use only skas mode (and the host has the skas patch applied to it),
-+ then it is OK to say N here.
-+
-+Force a static link
-+CONFIG_STATIC_LINK
-+ If CONFIG_MODE_TT is disabled, then this option gives you the ability
-+ to force a static link of UML. Normally, if only skas mode is built
-+ in to UML, it will be linked as a shared binary. This is inconvenient
-+ for use in a chroot jail. So, if you intend to run UML inside a
-+ chroot, and you disable CONFIG_MODE_TT, you probably want to say Y
-+ here.
-+
-+2G/2G host address space split
-+CONFIG_HOST_2G_2G
-+ Most Linux machines are configured so that the kernel occupies the
-+ upper 1G of the 4G address space and processes use the lower 3G.
-+ However, some machine are configured with a 2G/2G split, with the
-+ kernel occupying the upper 2G and processes using the lower 2G.
-+
-+ To allow UML to run on a such host you have to say Y here. N should be
-+ a safe choice most of the time.
-+
-+Kernel stack size order
-+CONFIG_KERNEL_STACK_ORDER
-+ This option determines the size of UML kernel stacks. They will
-+ be 1 << order pages. The default is OK unless you're running Valgrind
-+ on UML, in which case, set this to 3.
-+
-+UML ubd block driver
-+CONFIG_BLK_DEV_UBD
-+ The User-Mode Linux port includes a driver called UBD which will let
-+ you access arbitrary files on the host computer as block devices.
-+ Unless you know that you do not need such virtual block devices say
-+ Y here.
-+
- CONFIG_USB_GADGET
- USB is a master/slave protocol, organized with one master
- host (such as a PC) controlling up to 127 peripheral devices.
-@@ -15905,17 +15962,15 @@
-
- Always do synchronous disk IO for UBD
- CONFIG_BLK_DEV_UBD_SYNC
-- The User-Mode Linux port includes a driver called UBD which will let
-- you access arbitrary files on the host computer as block devices.
-- Writes to such a block device are not immediately written to the
-- host's disk; this may cause problems if, for example, the User-Mode
-- Linux 'Virtual Machine' uses a journalling file system and the host
-- computer crashes.
-+ Writes to the virtual block device are not immediately written to the host's
-+ disk; this may cause problems if, for example, the User-Mode Linux
-+ 'Virtual Machine' uses a journalling filesystem and the host computer
-+ crashes.
-
- Synchronous operation (i.e. always writing data to the host's disk
- immediately) is configurable on a per-UBD basis by using a special
- kernel command line option. Alternatively, you can say Y here to
-- turn on synchronous operation by default for all block.
-+ turn on synchronous operation by default for all block devices.
-
- If you're running a journalling file system (like reiserfs, for
- example) in your virtual machine, you will want to say Y here. If
-@@ -15927,6 +15982,7 @@
- CONFIG_PT_PROXY
- This option enables a debugging interface which allows gdb to debug
- the kernel without needing to actually attach to kernel threads.
-+ CONFIG_XTERM_CHAN must be enabled in order to enable CONFIG_PT_PROXY.
- If you want to do kernel debugging, say Y here; otherwise say N.
-
- Management console
-@@ -15959,7 +16015,7 @@
- This option allows developers to retrieve coverage data from a UML
- session.
-
-- See <http://user-mode-linux.sourceforge.net/gcov.html> for more
-+ See <http://user-mode-linux.sourceforge.net/gprof.html> for more
- details.
-
- If you're involved in UML kernel development and want to use gcov,
-@@ -15996,6 +16052,19 @@
- If you'd like to be able to work with files stored on the host,
- say Y or M here; otherwise say N.
-
-+HoneyPot ProcFS
-+CONFIG_HPPFS
-+ hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
-+ entries to be overridden, removed, or fabricated from the host.
-+ Its purpose is to allow a UML to appear to be a physical machine
-+ by removing or changing anything in /proc which gives away the
-+ identity of a UML.
-+
-+ See <http://user-mode-linux.sf.net/hppfs.html> for more information.
-+
-+ You only need this if you are setting up a UML honeypot. Otherwise,
-+ it is safe to say 'N' here.
-+
- Example IO Memory driver
- CONFIG_MMAPPER
- The User-Mode Linux port can provide support for IO Memory
-@@ -16011,6 +16080,21 @@
- If you'd like to be able to provide a simulated IO port space for
- User-Mode Linux processes, say Y. If unsure, say N.
-
-+Anonymous Memory support
-+CONFIG_DEV_ANON
-+ Don't ask. Just say Y.
-+
-+Support for software watchdog inside UML
-+CONFIG_UML_WATCHDOG
-+ Support for a virtual hardware watchdog. It's safe to say N here.
-+
-+COW block device
-+CONFIG_COW
-+ This is a layered driver which sits above two other block devices.
-+ One is read-only, and the other is a read-write layer which stores
-+ all changes. This provides the illusion that the read-only layer
-+ can be mounted read-write and changed.
-+
- Virtual Serial Line
- CONFIG_SSL
- The User-Mode Linux environment allows you to create virtual serial
-@@ -16121,26 +16205,197 @@
-
- SLIP transport
- CONFIG_UML_NET_SLIP
-- The Slip User-Mode Linux network transport allows a running UML to
-+ The slip User-Mode Linux network transport allows a running UML to
- network with its host over a point-to-point link. Unlike Ethertap,
- which can carry any Ethernet frame (and hence even non-IP packets),
-- the Slip transport can only carry IP packets.
-+ the slip transport can only carry IP packets.
-
-- To use this, your host must support Slip devices.
-+ To use this, your host must support slip devices.
-
- For more information, see
- <http://user-mode-linux.sourceforge.net/networking.html>. That site
-- has examples of the UML command line to use to enable Slip
-+ has examples of the UML command line to use to enable slip
- networking, and details of a few quirks with it.
-
-- The Ethertap Transport is preferred over Slip because of its
-- limitation. If you prefer Slip, however, say Y here. Otherwise
-+ The Ethertap Transport is preferred over slip because of its
-+ limitations. If you prefer slip, however, say Y here. Otherwise
- choose the Multicast transport (to network multiple UMLs on
- multiple hosts), Ethertap (to network with the host and the
- outside world), and/or the Daemon transport (to network multiple
- UMLs on a single host). You may choose more than one without
- conflict. If you don't need UML networking, say N.
-
-+SLiRP transport
-+CONFIG_UML_NET_SLIRP
-+ The SLiRP User-Mode Linux network transport allows a running UML
-+ to network by invoking a program that can handle SLIP encapsulated
-+ packets. This is commonly (but not limited to) the application
-+ known as SLiRP, a program that can re-socket IP packets back onto
-+ the host on which it is run. Only IP packets are supported,
-+ unlike other network transports that can handle all Ethernet
-+ frames. In general, slirp allows the UML the same IP connectivity
-+ to the outside world that the host user is permitted, and unlike
-+ other transports, SLiRP works without the need of root level
-+ privleges, setuid binaries, or SLIP devices on the host. This
-+ also means not every type of connection is possible, but most
-+ situations can be accomodated with carefully crafted slirp
-+ commands that can be passed along as part of the network device's
-+ setup string. The effect of this transport on the UML is similar
-+ that of a host behind a firewall that masquerades all network
-+ connections passing through it (but is less secure).
-+
-+ To use this you should first have slirp compiled somewhere
-+ accessible on the host, and have read its documentation. If you
-+ don't need UML networking, say N.
-+
-+ Startup example: "eth0=slirp,FE:FD:01:02:03:04,/usr/local/bin/slirp"
-+
-+pcap transport
-+CONFIG_UML_NET_PCAP
-+ The pcap transport makes a pcap packet stream on the host look
-+ like an ethernet device inside UML. This is useful for making
-+ UML act as a network monitor for the host. You must have libcap
-+ installed in order to build the pcap transport into UML.
-+
-+ For more information, see
-+ <http://user-mode-linux.sourceforge.net/networking.html> That site
-+ has examples of the UML command line to use to enable this option.
-+
-+ If you intend to use UML as a network monitor for the host, say
-+ Y here. Otherwise, say N.
-+
-+Default main console channel initialization
-+CONFIG_CON_ZERO_CHAN
-+ This is the string describing the channel to which the main console
-+ will be attached by default. This value can be overridden from the
-+ command line. The default value is "fd:0,fd:1", which attaches the
-+ main console to stdin and stdout.
-+ It is safe to leave this unchanged.
-+
-+Default console channel initialization
-+CONFIG_CON_CHAN
-+ This is the string describing the channel to which all consoles
-+ except the main console will be attached by default. This value can
-+ be overridden from the command line. The default value is "xterm",
-+ which brings them up in xterms.
-+ It is safe to leave this unchanged, although you may wish to change
-+ this if you expect the UML that you build to be run in environments
-+ which don't have X or xterm available.
-+
-+Default serial line channel initialization
-+CONFIG_SSL_CHAN
-+ This is the string describing the channel to which the serial lines
-+ will be attached by default. This value can be overridden from the
-+ command line. The default value is "pty", which attaches them to
-+ traditional pseudo-terminals.
-+ It is safe to leave this unchanged, although you may wish to change
-+ this if you expect the UML that you build to be run in environments
-+ which don't have a set of /dev/pty* devices.
-+
-+Nesting level
-+CONFIG_NEST_LEVEL
-+ This is set to the number of layers of UMLs that this UML will be run
-+ in. Normally, this is zero, meaning that it will run directly on the
-+ host. Setting it to one will build a UML that can run inside a UML
-+ that is running on the host. Generally, if you intend this UML to run
-+ inside another UML, set CONFIG_NEST_LEVEL to one more than the host UML.
-+ Note that if the hosting UML has its CONFIG_KERNEL_HALF_GIGS set to
-+ greater than one, then the guest UML should have its CONFIG_NEST_LEVEL
-+ set to the host's CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS.
-+ Only change this if you are running nested UMLs.
-+
-+Kernel address space size (in .5G units)
-+CONFIG_KERNEL_HALF_GIGS
-+ This determines the amount of address space that UML will allocate for
-+ its own, measured in half Gigabyte units. The default is 1.
-+ Change this only if you need to boot UML with an unusually large amount
-+ of physical memory.
-+
-+UML sound support
-+CONFIG_UML_SOUND
-+ This option enables UML sound support. If enabled, it will pull in
-+ soundcore and the UML hostaudio relay, which acts as a intermediary
-+ between the host's dsp and mixer devices and the UML sound system.
-+ It is safe to say 'Y' here.
-+
-+UML SMP support
-+CONFIG_UML_SMP
-+ This option enables UML SMP support. UML implements virtual SMP by
-+ allowing as many processes to run simultaneously on the host as
-+ there are virtual processors configured. Obviously, if the host is
-+ a uniprocessor, those processes will timeshare, but, inside UML,
-+ will appear to be running simultaneously. If the host is a
-+ multiprocessor, then UML processes may run simultaneously, depending
-+ on the host scheduler.
-+ CONFIG_SMP will be set to whatever this option is set to.
-+ It is safe to leave this unchanged.
-+
-+file descriptor channel support
-+CONFIG_FD_CHAN
-+ This option enables support for attaching UML consoles and serial
-+ lines to already set up file descriptors. Generally, the main
-+ console is attached to file descriptors 0 and 1 (stdin and stdout),
-+ so it would be wise to leave this enabled unless you intend to
-+ attach it to some other host device.
-+
-+null device channel support
-+CONFIG_NULL_CHAN
-+ This option enables support for attaching UML consoles and serial
-+ lines to a device similar to /dev/null. Data written to it disappears
-+ and there is never any data to be read.
-+
-+port channel support
-+CONFIG_PORT_CHAN
-+ This option enables support for attaching UML consoles and serial
-+ lines to host portals. They may be accessed with 'telnet <host>
-+ <port number>'. Any number of consoles and serial lines may be
-+ attached to a single portal, although what UML device you get when
-+ you telnet to that portal will be unpredictable.
-+ It is safe to say 'Y' here.
-+
-+pty channel support
-+CONFIG_PTY_CHAN
-+ This option enables support for attaching UML consoles and serial
-+ lines to host pseudo-terminals. Access to both traditional
-+ pseudo-terminals (/dev/pty*) and pts pseudo-terminals are controlled
-+ with this option. The assignment of UML devices to host devices
-+ will be announced in the kernel message log.
-+ It is safe to say 'Y' here.
-+
-+tty channel support
-+CONFIG_TTY_CHAN
-+ This option enables support for attaching UML consoles and serial
-+ lines to host terminals. Access to both virtual consoles
-+ (/dev/tty*) and the slave side of pseudo-terminals (/dev/ttyp* and
-+ /dev/pts/*) are controlled by this option.
-+ It is safe to say 'Y' here.
-+
-+xterm channel support
-+CONFIG_XTERM_CHAN
-+ This option enables support for attaching UML consoles and serial
-+ lines to xterms. Each UML device so assigned will be brought up in
-+ its own xterm.
-+ If you disable this option, then CONFIG_PT_PROXY will be disabled as
-+ well, since UML's gdb currently requires an xterm.
-+ It is safe to say 'Y' here.
-+
-+tty logging
-+CONFIG_TTY_LOG
-+ This option enables logging of all data going through pseudo-terminals
-+ to the host. This is primarily useful for honeypots, where you want
-+ secure keystroke logging that can't be detected or disabled by root.
-+ Say 'N' unless you are setting up a UML honeypot or otherwise know that
-+ you want this option.
-+
-+UML real-time clock support
-+CONFIG_UML_REAL_TIME_CLOCK
-+ This option ties the UML clock to the host clock, so that time passes at
-+ the same rate as on the host, regardless of how much CPU time the UML is
-+ getting. This should normally be enabled. The exception would be if you're
-+ debugging UML. In this case, time spent staring at the debugger with UML
-+ stopped will cause lots of timer ticks to be backed up, and UML will spent
-+ lots of time calling the timer when it is finally continued.
-+
- Microtek USB scanner support
- CONFIG_USB_MICROTEK
- Say Y here if you want support for the Microtek X6USB and
-diff -Naur -X ../exclude-files orig/drivers/char/Makefile um/drivers/char/Makefile
---- orig/drivers/char/Makefile 2003-12-16 22:16:26.000000000 -0500
-+++ um/drivers/char/Makefile 2003-12-16 22:17:25.000000000 -0500
-@@ -109,6 +109,12 @@
- endif
- endif
-
-+ifeq ($(ARCH),um)
-+ KEYMAP =
-+ KEYBD =
-+ CONSOLE =
-+endif
-+
- ifeq ($(ARCH),sh)
- KEYMAP =
- KEYBD =
-diff -Naur -X ../exclude-files orig/drivers/char/mem.c um/drivers/char/mem.c
---- orig/drivers/char/mem.c 2003-12-16 22:16:27.000000000 -0500
-+++ um/drivers/char/mem.c 2004-01-05 11:23:32.000000000 -0500
-@@ -220,7 +220,8 @@
- ssize_t read = 0;
- ssize_t virtr = 0;
- char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
--
-+
-+ p = (unsigned long) __va(p);
- if (p < (unsigned long) high_memory) {
- read = count;
- if (count > (unsigned long) high_memory - p)
-@@ -269,7 +270,7 @@
- }
- free_page((unsigned long)kbuf);
- }
-- *ppos = p;
-+ *ppos = __pa((void *) p);
- return virtr + read;
- }
-
-@@ -664,6 +665,8 @@
- write: write_full,
- };
-
-+extern struct file_operations anon_file_operations;
-+
- static int memory_open(struct inode * inode, struct file * filp)
- {
- switch (MINOR(inode->i_rdev)) {
-@@ -693,6 +696,9 @@
- case 9:
- filp->f_op = &urandom_fops;
- break;
-+ case 10:
-+ filp->f_op = &anon_file_operations;
-+ break;
- default:
- return -ENXIO;
- }
-@@ -719,7 +725,8 @@
- {5, "zero", S_IRUGO | S_IWUGO, &zero_fops},
- {7, "full", S_IRUGO | S_IWUGO, &full_fops},
- {8, "random", S_IRUGO | S_IWUSR, &random_fops},
-- {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops}
-+ {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops},
-+ {10, "anon", S_IRUGO | S_IWUSR, &anon_file_operations},
- };
- int i;
-
-diff -Naur -X ../exclude-files orig/drivers/char/tty_io.c um/drivers/char/tty_io.c
---- orig/drivers/char/tty_io.c 2003-12-16 22:16:27.000000000 -0500
-+++ um/drivers/char/tty_io.c 2003-12-16 22:17:25.000000000 -0500
-@@ -649,6 +649,23 @@
- wake_up_interruptible(&tty->write_wait);
- }
-
-+#ifdef CONFIG_TTY_LOG
-+
-+int (*open_log)(void *, void *) = NULL;
-+int (*write_log)(int, const char *, int, void *, int) = NULL;
-+void (*close_log)(int, void *) = NULL;
-+
-+void register_tty_logger(int (*opener)(void *, void *),
-+ int (*writer)(int, const char *, int, void *, int),
-+ void (*closer)(int, void *))
-+{
-+ open_log = opener;
-+ write_log = writer;
-+ close_log = closer;
-+}
-+
-+#endif
-+
- static ssize_t tty_read(struct file * file, char * buf, size_t count,
- loff_t *ppos)
- {
-@@ -689,8 +706,13 @@
- else
- i = -EIO;
- unlock_kernel();
-- if (i > 0)
-+ if (i > 0){
- inode->i_atime = CURRENT_TIME;
-+#ifdef CONFIG_TTY_LOG
-+ if((tty->log_fd >= 0) && (write_log != NULL))
-+ (*write_log)(tty->log_fd, buf, i, tty, 1);
-+#endif
-+ }
- return i;
- }
-
-@@ -744,6 +766,10 @@
- if (written) {
- file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
- ret = written;
-+#ifdef CONFIG_TTY_LOG
-+ if((tty->log_fd >= 0) && (write_log != NULL))
-+ (*write_log)(tty->log_fd, buf - ret, ret, tty, 0);
-+#endif
- }
- up(&tty->atomic_write);
- return ret;
-@@ -971,6 +997,7 @@
- goto release_mem_out;
- }
- }
-+
- goto success;
-
- /*
-@@ -1290,6 +1317,11 @@
- run_task_queue(&tq_timer);
- flush_scheduled_tasks();
-
-+#ifdef CONFIG_TTY_LOG
-+ if((tty->log_fd >= 0) && (close_log != NULL))
-+ (*close_log)(tty->log_fd, tty);
-+#endif
-+
- /*
- * The release_mem function takes care of the details of clearing
- * the slots and preserving the termios structure.
-@@ -1448,6 +1480,11 @@
- nr_warns++;
- }
- }
-+
-+#ifdef CONFIG_TTY_LOG
-+ if((tty->log_fd < 0) && (open_log != NULL))
-+ tty->log_fd = (*open_log)(tty, current->tty);
-+#endif
- return 0;
- }
-
-@@ -2047,6 +2084,9 @@
- spin_lock_init(&tty->read_lock);
- INIT_LIST_HEAD(&tty->tty_files);
- INIT_TQUEUE(&tty->SAK_tq, 0, 0);
-+#ifdef CONFIG_TTY_LOG
-+ tty->log_fd = -1;
-+#endif
- }
-
- /*
-diff -Naur -X ../exclude-files orig/drivers/net/setup.c um/drivers/net/setup.c
---- orig/drivers/net/setup.c 2002-09-15 12:13:19.000000000 -0400
-+++ um/drivers/net/setup.c 2003-10-21 03:26:07.000000000 -0400
-@@ -28,7 +28,6 @@
- extern int lmc_setup(void);
-
- extern int madgemc_probe(void);
--extern int uml_net_probe(void);
-
- /* Pad device name to IFNAMSIZ=16. F.e. __PAD6 is string of 9 zeros. */
- #define __PAD6 "\0\0\0\0\0\0\0\0\0"
-@@ -103,9 +102,6 @@
- #ifdef CONFIG_MADGEMC
- {madgemc_probe, 0},
- #endif
--#ifdef CONFIG_UML_NET
-- {uml_net_probe, 0},
--#endif
-
- {NULL, 0},
- };
-diff -Naur -X ../exclude-files orig/fs/bad_inode.c um/fs/bad_inode.c
---- orig/fs/bad_inode.c 2002-08-21 11:47:27.000000000 -0400
-+++ um/fs/bad_inode.c 2003-10-21 03:26:07.000000000 -0400
-@@ -83,6 +83,7 @@
-
- void make_bad_inode(struct inode * inode)
- {
-+ inode->i_state = 0;
- inode->i_mode = S_IFREG;
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- inode->i_op = &bad_inode_ops;
-diff -Naur -X ../exclude-files orig/include/asm-i386/hardirq.h um/include/asm-i386/hardirq.h
---- orig/include/asm-i386/hardirq.h 2004-01-11 22:46:12.000000000 -0500
-+++ um/include/asm-i386/hardirq.h 2004-02-14 06:28:59.000000000 -0500
-@@ -4,6 +4,7 @@
- #include <linux/config.h>
- #include <linux/threads.h>
- #include <linux/irq.h>
-+#include <asm/processor.h> /* for cpu_relax */
-
- /* assembly code in softirq.h is sensitive to the offsets of these fields */
- typedef struct {
-diff -Naur -X ../exclude-files orig/include/asm-um/a.out.h um/include/asm-um/a.out.h
---- orig/include/asm-um/a.out.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/a.out.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,20 @@
-+#ifndef __UM_A_OUT_H
-+#define __UM_A_OUT_H
-+
-+#include "linux/config.h"
-+#include "asm/arch/a.out.h"
-+#include "choose-mode.h"
-+
-+#undef STACK_TOP
-+
-+extern unsigned long stacksizelim;
-+
-+extern unsigned long host_task_size;
-+
-+#define STACK_ROOM (stacksizelim)
-+
-+extern int honeypot;
-+#define STACK_TOP \
-+ CHOOSE_MODE((honeypot ? host_task_size : task_size), task_size)
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/archparam-i386.h um/include/asm-um/archparam-i386.h
---- orig/include/asm-um/archparam-i386.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/archparam-i386.h 2003-12-16 08:50:39.000000000 -0500
-@@ -0,0 +1,80 @@
-+/*
-+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UM_ARCHPARAM_I386_H
-+#define __UM_ARCHPARAM_I386_H
-+
-+/********* Bits for asm-um/elf.h ************/
-+
-+#include "user.h"
-+
-+#define ELF_PLATFORM "i586"
-+
-+#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
-+
-+typedef struct user_i387_struct elf_fpregset_t;
-+typedef unsigned long elf_greg_t;
-+
-+#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
-+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-+
-+#define ELF_DATA ELFDATA2LSB
-+#define ELF_ARCH EM_386
-+
-+#define ELF_PLAT_INIT(regs, load_addr) do { \
-+ PT_REGS_EBX(regs) = 0; \
-+ PT_REGS_ECX(regs) = 0; \
-+ PT_REGS_EDX(regs) = 0; \
-+ PT_REGS_ESI(regs) = 0; \
-+ PT_REGS_EDI(regs) = 0; \
-+ PT_REGS_EBP(regs) = 0; \
-+ PT_REGS_EAX(regs) = 0; \
-+} while(0)
-+
-+/* Shamelessly stolen from include/asm-i386/elf.h */
-+
-+#define ELF_CORE_COPY_REGS(pr_reg, regs) do { \
-+ pr_reg[0] = PT_REGS_EBX(regs); \
-+ pr_reg[1] = PT_REGS_ECX(regs); \
-+ pr_reg[2] = PT_REGS_EDX(regs); \
-+ pr_reg[3] = PT_REGS_ESI(regs); \
-+ pr_reg[4] = PT_REGS_EDI(regs); \
-+ pr_reg[5] = PT_REGS_EBP(regs); \
-+ pr_reg[6] = PT_REGS_EAX(regs); \
-+ pr_reg[7] = PT_REGS_DS(regs); \
-+ pr_reg[8] = PT_REGS_ES(regs); \
-+ /* fake once used fs and gs selectors? */ \
-+ pr_reg[9] = PT_REGS_DS(regs); \
-+ pr_reg[10] = PT_REGS_DS(regs); \
-+ pr_reg[11] = PT_REGS_SYSCALL_NR(regs); \
-+ pr_reg[12] = PT_REGS_IP(regs); \
-+ pr_reg[13] = PT_REGS_CS(regs); \
-+ pr_reg[14] = PT_REGS_EFLAGS(regs); \
-+ pr_reg[15] = PT_REGS_SP(regs); \
-+ pr_reg[16] = PT_REGS_SS(regs); \
-+} while(0);
-+
-+/********* Bits for asm-um/delay.h **********/
-+
-+typedef unsigned long um_udelay_t;
-+
-+/********* Nothing for asm-um/hardirq.h **********/
-+
-+/********* Nothing for asm-um/hw_irq.h **********/
-+
-+/********* Nothing for asm-um/string.h **********/
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/include/asm-um/archparam-ppc.h um/include/asm-um/archparam-ppc.h
---- orig/include/asm-um/archparam-ppc.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/archparam-ppc.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,41 @@
-+#ifndef __UM_ARCHPARAM_PPC_H
-+#define __UM_ARCHPARAM_PPC_H
-+
-+/********* Bits for asm-um/elf.h ************/
-+
-+#define ELF_PLATFORM (0)
-+
-+#define ELF_ET_DYN_BASE (0x08000000)
-+
-+/* the following stolen from asm-ppc/elf.h */
-+#define ELF_NGREG 48 /* includes nip, msr, lr, etc. */
-+#define ELF_NFPREG 33 /* includes fpscr */
-+/* General registers */
-+typedef unsigned long elf_greg_t;
-+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-+
-+/* Floating point registers */
-+typedef double elf_fpreg_t;
-+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
-+
-+#define ELF_DATA ELFDATA2MSB
-+#define ELF_ARCH EM_PPC
-+
-+/********* Bits for asm-um/delay.h **********/
-+
-+typedef unsigned int um_udelay_t;
-+
-+/********* Bits for asm-um/hw_irq.h **********/
-+
-+struct hw_interrupt_type;
-+
-+/********* Bits for asm-um/hardirq.h **********/
-+
-+#define irq_enter(cpu, irq) hardirq_enter(cpu)
-+#define irq_exit(cpu, irq) hardirq_exit(cpu)
-+
-+/********* Bits for asm-um/string.h **********/
-+
-+#define __HAVE_ARCH_STRRCHR
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/arch-signal-i386.h um/include/asm-um/arch-signal-i386.h
---- orig/include/asm-um/arch-signal-i386.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/arch-signal-i386.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,24 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UM_ARCH_SIGNAL_I386_H
-+#define __UM_ARCH_SIGNAL_I386_H
-+
-+struct arch_signal_context {
-+ unsigned long extrasigs[_NSIG_WORDS];
-+};
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/include/asm-um/atomic.h um/include/asm-um/atomic.h
---- orig/include/asm-um/atomic.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/atomic.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,6 @@
-+#ifndef __UM_ATOMIC_H
-+#define __UM_ATOMIC_H
-+
-+#include "asm/arch/atomic.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/bitops.h um/include/asm-um/bitops.h
---- orig/include/asm-um/bitops.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/bitops.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,6 @@
-+#ifndef __UM_BITOPS_H
-+#define __UM_BITOPS_H
-+
-+#include "asm/arch/bitops.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/boot.h um/include/asm-um/boot.h
---- orig/include/asm-um/boot.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/boot.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_BOOT_H
-+#define __UM_BOOT_H
-+
-+#include "asm/arch/boot.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/bugs.h um/include/asm-um/bugs.h
---- orig/include/asm-um/bugs.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/bugs.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_BUGS_H
-+#define __UM_BUGS_H
-+
-+void check_bugs(void);
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/byteorder.h um/include/asm-um/byteorder.h
---- orig/include/asm-um/byteorder.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/byteorder.h 2004-01-16 03:32:58.000000000 -0500
-@@ -0,0 +1,6 @@
-+#ifndef __UM_BYTEORDER_H
-+#define __UM_BYTEORDER_H
-+
-+#include "asm/arch/byteorder.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/cache.h um/include/asm-um/cache.h
---- orig/include/asm-um/cache.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/cache.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_CACHE_H
-+#define __UM_CACHE_H
-+
-+#define L1_CACHE_BYTES 32
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/checksum.h um/include/asm-um/checksum.h
---- orig/include/asm-um/checksum.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/checksum.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_CHECKSUM_H
-+#define __UM_CHECKSUM_H
-+
-+#include "sysdep/checksum.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/cobalt.h um/include/asm-um/cobalt.h
---- orig/include/asm-um/cobalt.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/cobalt.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_COBALT_H
-+#define __UM_COBALT_H
-+
-+#include "asm/arch/cobalt.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/current.h um/include/asm-um/current.h
---- orig/include/asm-um/current.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/current.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,34 @@
-+/*
-+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UM_CURRENT_H
-+#define __UM_CURRENT_H
-+
-+#ifndef __ASSEMBLY__
-+
-+#include "linux/config.h"
-+#include "asm/page.h"
-+
-+struct task_struct;
-+
-+#define CURRENT_TASK(dummy) (((unsigned long) &dummy) & \
-+ (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER))
-+
-+#define current ({ int dummy; (struct task_struct *) CURRENT_TASK(dummy); })
-+
-+#endif /* __ASSEMBLY__ */
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/include/asm-um/delay.h um/include/asm-um/delay.h
---- orig/include/asm-um/delay.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/delay.h 2003-12-16 22:26:58.000000000 -0500
-@@ -0,0 +1,7 @@
-+#ifndef __UM_DELAY_H
-+#define __UM_DELAY_H
-+
-+#include "asm/arch/delay.h"
-+#include "asm/archparam.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/desc.h um/include/asm-um/desc.h
---- orig/include/asm-um/desc.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/desc.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_DESC_H
-+#define __UM_DESC_H
-+
-+#include "asm/arch/desc.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/div64.h um/include/asm-um/div64.h
---- orig/include/asm-um/div64.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/div64.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef _UM_DIV64_H
-+#define _UM_DIV64_H
-+
-+#include "asm/arch/div64.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/dma.h um/include/asm-um/dma.h
---- orig/include/asm-um/dma.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/dma.h 2004-01-16 03:32:59.000000000 -0500
-@@ -0,0 +1,10 @@
-+#ifndef __UM_DMA_H
-+#define __UM_DMA_H
-+
-+#include "asm/io.h"
-+
-+extern unsigned long uml_physmem;
-+
-+#define MAX_DMA_ADDRESS (uml_physmem)
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/elf.h um/include/asm-um/elf.h
---- orig/include/asm-um/elf.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/elf.h 2003-12-16 22:29:20.000000000 -0500
-@@ -0,0 +1,18 @@
-+#ifndef __UM_ELF_H
-+#define __UM_ELF_H
-+
-+#include "asm/archparam.h"
-+
-+#define ELF_HWCAP (0)
-+
-+#define SET_PERSONALITY(ex, ibcs2) do ; while(0)
-+
-+#define ELF_EXEC_PAGESIZE 4096
-+
-+#define elf_check_arch(x) (1)
-+
-+#define ELF_CLASS ELFCLASS32
-+
-+#define USE_ELF_CORE_DUMP
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/errno.h um/include/asm-um/errno.h
---- orig/include/asm-um/errno.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/errno.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_ERRNO_H
-+#define __UM_ERRNO_H
-+
-+#include "asm/arch/errno.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/fcntl.h um/include/asm-um/fcntl.h
---- orig/include/asm-um/fcntl.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/fcntl.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_FCNTL_H
-+#define __UM_FCNTL_H
-+
-+#include "asm/arch/fcntl.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/fixmap.h um/include/asm-um/fixmap.h
---- orig/include/asm-um/fixmap.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/fixmap.h 2004-02-14 06:29:00.000000000 -0500
-@@ -0,0 +1,89 @@
-+#ifndef __UM_FIXMAP_H
-+#define __UM_FIXMAP_H
-+
-+#include <linux/config.h>
-+#include <asm/kmap_types.h>
-+
-+/*
-+ * Here we define all the compile-time 'special' virtual
-+ * addresses. The point is to have a constant address at
-+ * compile time, but to set the physical address only
-+ * in the boot process. We allocate these special addresses
-+ * from the end of virtual memory (0xfffff000) backwards.
-+ * Also this lets us do fail-safe vmalloc(), we
-+ * can guarantee that these special addresses and
-+ * vmalloc()-ed addresses never overlap.
-+ *
-+ * these 'compile-time allocated' memory buffers are
-+ * fixed-size 4k pages. (or larger if used with an increment
-+ * highger than 1) use fixmap_set(idx,phys) to associate
-+ * physical memory with fixmap indices.
-+ *
-+ * TLB entries of such buffers will not be flushed across
-+ * task switches.
-+ */
-+
-+/*
-+ * on UP currently we will have no trace of the fixmap mechanizm,
-+ * no page table allocations, etc. This might change in the
-+ * future, say framebuffers for the console driver(s) could be
-+ * fix-mapped?
-+ */
-+enum fixed_addresses {
-+#ifdef CONFIG_HIGHMEM
-+ FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
-+ FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
-+#endif
-+ __end_of_fixed_addresses
-+};
-+
-+extern void __set_fixmap (enum fixed_addresses idx,
-+ unsigned long phys, pgprot_t flags);
-+
-+#define set_fixmap(idx, phys) \
-+ __set_fixmap(idx, phys, PAGE_KERNEL)
-+/*
-+ * Some hardware wants to get fixmapped without caching.
-+ */
-+#define set_fixmap_nocache(idx, phys) \
-+ __set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
-+/*
-+ * used by vmalloc.c.
-+ *
-+ * Leave one empty page between vmalloc'ed areas and
-+ * the start of the fixmap, and leave one page empty
-+ * at the top of mem..
-+ */
-+extern unsigned long get_kmem_end(void);
-+
-+#define FIXADDR_TOP (get_kmem_end() - 0x2000)
-+#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
-+#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
-+
-+#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
-+
-+extern void __this_fixmap_does_not_exist(void);
-+
-+/*
-+ * 'index to address' translation. If anyone tries to use the idx
-+ * directly without tranlation, we catch the bug with a NULL-deference
-+ * kernel oops. Illegal ranges of incoming indices are caught too.
-+ */
-+static inline unsigned long fix_to_virt(const unsigned int idx)
-+{
-+ /*
-+ * this branch gets completely eliminated after inlining,
-+ * except when someone tries to use fixaddr indices in an
-+ * illegal way. (such as mixing up address types or using
-+ * out-of-range indices).
-+ *
-+ * If it doesn't get removed, the linker will complain
-+ * loudly with a reasonably clear error message..
-+ */
-+ if (idx >= __end_of_fixed_addresses)
-+ __this_fixmap_does_not_exist();
-+
-+ return __fix_to_virt(idx);
-+}
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/floppy.h um/include/asm-um/floppy.h
---- orig/include/asm-um/floppy.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/floppy.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_FLOPPY_H
-+#define __UM_FLOPPY_H
-+
-+#include "asm/arch/floppy.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/hardirq.h um/include/asm-um/hardirq.h
---- orig/include/asm-um/hardirq.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/hardirq.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,6 @@
-+#ifndef __UM_HARDIRQ_H
-+#define __UM_HARDIRQ_H
-+
-+#include "asm/arch/hardirq.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/hdreg.h um/include/asm-um/hdreg.h
---- orig/include/asm-um/hdreg.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/hdreg.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_HDREG_H
-+#define __UM_HDREG_H
-+
-+#include "asm/arch/hdreg.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/highmem.h um/include/asm-um/highmem.h
---- orig/include/asm-um/highmem.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/highmem.h 2004-02-14 06:29:00.000000000 -0500
-@@ -0,0 +1,12 @@
-+#ifndef __UM_HIGHMEM_H
-+#define __UM_HIGHMEM_H
-+
-+#include "asm/page.h"
-+#include "asm/fixmap.h"
-+#include "asm/arch/highmem.h"
-+
-+#undef PKMAP_BASE
-+
-+#define PKMAP_BASE ((FIXADDR_START - LAST_PKMAP * PAGE_SIZE) & PMD_MASK)
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/hw_irq.h um/include/asm-um/hw_irq.h
---- orig/include/asm-um/hw_irq.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/hw_irq.h 2003-12-16 22:26:55.000000000 -0500
-@@ -0,0 +1,10 @@
-+#ifndef _ASM_UM_HW_IRQ_H
-+#define _ASM_UM_HW_IRQ_H
-+
-+#include "asm/irq.h"
-+#include "asm/archparam.h"
-+
-+static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i)
-+{}
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/ide.h um/include/asm-um/ide.h
---- orig/include/asm-um/ide.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/ide.h 2004-01-16 23:40:52.000000000 -0500
-@@ -0,0 +1,6 @@
-+#ifndef __UM_IDE_H
-+#define __UM_IDE_H
-+
-+#include "asm/arch/ide.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/init.h um/include/asm-um/init.h
---- orig/include/asm-um/init.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/init.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,11 @@
-+#ifndef _UM_INIT_H
-+#define _UM_INIT_H
-+
-+#ifdef notdef
-+#define __init
-+#define __initdata
-+#define __initfunc(__arginit) __arginit
-+#define __cacheline_aligned
-+#endif
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/ioctl.h um/include/asm-um/ioctl.h
---- orig/include/asm-um/ioctl.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/ioctl.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_IOCTL_H
-+#define __UM_IOCTL_H
-+
-+#include "asm/arch/ioctl.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/ioctls.h um/include/asm-um/ioctls.h
---- orig/include/asm-um/ioctls.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/ioctls.h 2003-11-07 02:10:43.000000000 -0500
-@@ -0,0 +1,6 @@
-+#ifndef __UM_IOCTLS_H
-+#define __UM_IOCTLS_H
-+
-+#include "asm/arch/ioctls.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/io.h um/include/asm-um/io.h
---- orig/include/asm-um/io.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/io.h 2004-01-16 03:32:59.000000000 -0500
-@@ -0,0 +1,25 @@
-+#ifndef __UM_IO_H
-+#define __UM_IO_H
-+
-+#include "asm/page.h"
-+
-+#define IO_SPACE_LIMIT 0xdeadbeef /* Sure hope nothing uses this */
-+
-+static inline int inb(unsigned long i) { return(0); }
-+static inline void outb(char c, unsigned long i) { }
-+
-+/*
-+ * Change virtual addresses to physical addresses and vv.
-+ * These are pretty trivial
-+ */
-+static inline unsigned long virt_to_phys(volatile void * address)
-+{
-+ return __pa((void *) address);
-+}
-+
-+static inline void * phys_to_virt(unsigned long address)
-+{
-+ return __va(address);
-+}
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/ipcbuf.h um/include/asm-um/ipcbuf.h
---- orig/include/asm-um/ipcbuf.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/ipcbuf.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_IPCBUF_H
-+#define __UM_IPCBUF_H
-+
-+#include "asm/arch/ipcbuf.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/ipc.h um/include/asm-um/ipc.h
---- orig/include/asm-um/ipc.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/ipc.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_IPC_H
-+#define __UM_IPC_H
-+
-+#include "asm/arch/ipc.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/irq.h um/include/asm-um/irq.h
---- orig/include/asm-um/irq.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/irq.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,22 @@
-+#ifndef __UM_IRQ_H
-+#define __UM_IRQ_H
-+
-+#define TIMER_IRQ 0
-+#define UMN_IRQ 1
-+#define CONSOLE_IRQ 2
-+#define CONSOLE_WRITE_IRQ 3
-+#define UBD_IRQ 4
-+#define UM_ETH_IRQ 5
-+#define SSL_IRQ 6
-+#define SSL_WRITE_IRQ 7
-+#define ACCEPT_IRQ 8
-+#define MCONSOLE_IRQ 9
-+#define WINCH_IRQ 10
-+#define SIGIO_WRITE_IRQ 11
-+#define TELNETD_IRQ 12
-+#define XTERM_IRQ 13
-+
-+#define LAST_IRQ XTERM_IRQ
-+#define NR_IRQS (LAST_IRQ + 1)
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/keyboard.h um/include/asm-um/keyboard.h
---- orig/include/asm-um/keyboard.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/keyboard.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_KEYBOARD_H
-+#define __UM_KEYBOARD_H
-+
-+#include "asm/arch/keyboard.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/kmap_types.h um/include/asm-um/kmap_types.h
---- orig/include/asm-um/kmap_types.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/kmap_types.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,11 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UM_KMAP_TYPES_H
-+#define __UM_KMAP_TYPES_H
-+
-+#include "asm/arch/kmap_types.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/linux_logo.h um/include/asm-um/linux_logo.h
---- orig/include/asm-um/linux_logo.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/linux_logo.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_LINUX_LOGO_H
-+#define __UM_LINUX_LOGO_H
-+
-+#include "asm/arch/linux_logo.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/locks.h um/include/asm-um/locks.h
---- orig/include/asm-um/locks.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/locks.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_LOCKS_H
-+#define __UM_LOCKS_H
-+
-+#include "asm/arch/locks.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/mca_dma.h um/include/asm-um/mca_dma.h
---- orig/include/asm-um/mca_dma.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/mca_dma.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef mca___UM_DMA_H
-+#define mca___UM_DMA_H
-+
-+#include "asm/arch/mca_dma.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/mman.h um/include/asm-um/mman.h
---- orig/include/asm-um/mman.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/mman.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_MMAN_H
-+#define __UM_MMAN_H
-+
-+#include "asm/arch/mman.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/mmu_context.h um/include/asm-um/mmu_context.h
---- orig/include/asm-um/mmu_context.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/mmu_context.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,72 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UM_MMU_CONTEXT_H
-+#define __UM_MMU_CONTEXT_H
-+
-+#include "linux/sched.h"
-+#include "choose-mode.h"
-+
-+#define get_mmu_context(task) do ; while(0)
-+#define activate_context(tsk) do ; while(0)
-+
-+static inline void activate_mm(struct mm_struct *old, struct mm_struct *new)
-+{
-+}
-+
-+extern void switch_mm_skas(int mm_fd);
-+
-+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
-+ struct task_struct *tsk, unsigned cpu)
-+{
-+ if(prev != next){
-+ clear_bit(cpu, &prev->cpu_vm_mask);
-+ set_bit(cpu, &next->cpu_vm_mask);
-+ if(next != &init_mm)
-+ CHOOSE_MODE((void) 0,
-+ switch_mm_skas(next->context.skas.mm_fd));
-+ }
-+}
-+
-+static inline void enter_lazy_tlb(struct mm_struct *mm,
-+ struct task_struct *tsk, unsigned cpu)
-+{
-+}
-+
-+extern int init_new_context_skas(struct task_struct *task,
-+ struct mm_struct *mm);
-+
-+static inline int init_new_context_tt(struct task_struct *task,
-+ struct mm_struct *mm)
-+{
-+ return(0);
-+}
-+
-+static inline int init_new_context(struct task_struct *task,
-+ struct mm_struct *mm)
-+{
-+ return(CHOOSE_MODE_PROC(init_new_context_tt, init_new_context_skas,
-+ task, mm));
-+}
-+
-+extern void destroy_context_skas(struct mm_struct *mm);
-+
-+static inline void destroy_context(struct mm_struct *mm)
-+{
-+ CHOOSE_MODE((void) 0, destroy_context_skas(mm));
-+}
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/include/asm-um/mmu.h um/include/asm-um/mmu.h
---- orig/include/asm-um/mmu.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/mmu.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,22 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __MMU_H
-+#define __MMU_H
-+
-+#include "um_mmu.h"
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/include/asm-um/module.h um/include/asm-um/module.h
---- orig/include/asm-um/module.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/module.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_MODULE_H
-+#define __UM_MODULE_H
-+
-+#include "asm/arch/module.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/msgbuf.h um/include/asm-um/msgbuf.h
---- orig/include/asm-um/msgbuf.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/msgbuf.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_MSGBUF_H
-+#define __UM_MSGBUF_H
-+
-+#include "asm/arch/msgbuf.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/mtrr.h um/include/asm-um/mtrr.h
---- orig/include/asm-um/mtrr.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/mtrr.h 2004-02-12 05:46:29.000000000 -0500
-@@ -0,0 +1,6 @@
-+#ifndef __UM_MTRR_H
-+#define __UM_MTRR_H
-+
-+#include "asm/arch/mtrr.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/namei.h um/include/asm-um/namei.h
---- orig/include/asm-um/namei.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/namei.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_NAMEI_H
-+#define __UM_NAMEI_H
-+
-+#include "asm/arch/namei.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/page.h um/include/asm-um/page.h
---- orig/include/asm-um/page.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/page.h 2004-01-16 03:32:58.000000000 -0500
-@@ -0,0 +1,68 @@
-+/*
-+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UM_PAGE_H
-+#define __UM_PAGE_H
-+
-+struct page;
-+
-+#include "asm/arch/page.h"
-+
-+#undef BUG
-+#undef PAGE_BUG
-+#undef __pa
-+#undef __va
-+#undef virt_to_page
-+#undef VALID_PAGE
-+#undef PAGE_OFFSET
-+#undef KERNELBASE
-+
-+extern unsigned long uml_physmem;
-+
-+#define PAGE_OFFSET (uml_physmem)
-+#define KERNELBASE PAGE_OFFSET
-+
-+#ifndef __ASSEMBLY__
-+
-+extern void stop(void);
-+
-+#define BUG() do { \
-+ panic("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
-+} while (0)
-+
-+#define PAGE_BUG(page) do { \
-+ BUG(); \
-+} while (0)
-+
-+#endif /* __ASSEMBLY__ */
-+
-+#define __va_space (8*1024*1024)
-+
-+extern unsigned long to_phys(void *virt);
-+extern void *to_virt(unsigned long phys);
-+
-+#define __pa(virt) to_phys((void *) virt)
-+#define __va(phys) to_virt((unsigned long) phys)
-+
-+#define VALID_PAGE(page) ((page - mem_map) < max_mapnr)
-+
-+extern struct page *arch_validate(struct page *page, int mask, int order);
-+#define HAVE_ARCH_VALIDATE
-+
-+extern void arch_free_page(struct page *page, int order);
-+#define HAVE_ARCH_FREE_PAGE
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/include/asm-um/page_offset.h um/include/asm-um/page_offset.h
---- orig/include/asm-um/page_offset.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/page_offset.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1 @@
-+#define PAGE_OFFSET_RAW (uml_physmem)
-diff -Naur -X ../exclude-files orig/include/asm-um/param.h um/include/asm-um/param.h
---- orig/include/asm-um/param.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/param.h 2004-02-13 02:26:52.000000000 -0500
-@@ -0,0 +1,22 @@
-+#ifndef _UM_PARAM_H
-+#define _UM_PARAM_H
-+
-+#define HZ 100
-+
-+#define EXEC_PAGESIZE 4096
-+
-+#ifndef NGROUPS
-+#define NGROUPS 32
-+#endif
-+
-+#ifndef NOGROUP
-+#define NOGROUP (-1)
-+#endif
-+
-+#define MAXHOSTNAMELEN 64 /* max length of hostname */
-+
-+#ifdef __KERNEL__
-+# define CLOCKS_PER_SEC 100 /* frequency at which times() counts */
-+#endif
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/pci.h um/include/asm-um/pci.h
---- orig/include/asm-um/pci.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/pci.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_PCI_H
-+#define __UM_PCI_H
-+
-+#define PCI_DMA_BUS_IS_PHYS (1)
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/pgalloc.h um/include/asm-um/pgalloc.h
---- orig/include/asm-um/pgalloc.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/pgalloc.h 2004-02-14 06:29:00.000000000 -0500
-@@ -0,0 +1,164 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Derived from include/asm-i386/pgalloc.h and include/asm-i386/pgtable.h
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UM_PGALLOC_H
-+#define __UM_PGALLOC_H
-+
-+#include "linux/config.h"
-+#include "linux/mm.h"
-+#include "asm/fixmap.h"
-+#include "choose-mode.h"
-+
-+#define pgd_quicklist (current_cpu_data.pgd_quick)
-+#define pmd_quicklist (current_cpu_data.pmd_quick)
-+#define pte_quicklist (current_cpu_data.pte_quick)
-+#define pgtable_cache_size (current_cpu_data.pgtable_cache_sz)
-+
-+#define pmd_populate(mm, pmd, pte) set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
-+
-+/*
-+ * Allocate and free page tables.
-+ */
-+
-+static inline pgd_t *get_pgd_slow_tt(void)
-+{
-+ pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL);
-+
-+ if (pgd) {
-+ memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
-+ memcpy(pgd + USER_PTRS_PER_PGD,
-+ swapper_pg_dir + USER_PTRS_PER_PGD,
-+ (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
-+ }
-+ return pgd;
-+}
-+
-+static inline pgd_t *get_pgd_slow_skas(void)
-+{
-+ pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL);
-+
-+ if (pgd)
-+ memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
-+ return pgd;
-+}
-+
-+static inline pgd_t *get_pgd_slow(void)
-+{
-+ return(CHOOSE_MODE(get_pgd_slow_tt(), get_pgd_slow_skas()));
-+}
-+
-+static inline pgd_t *get_pgd_fast(void)
-+{
-+ unsigned long *ret;
-+
-+ ret = pgd_quicklist;
-+ if (ret != NULL) {
-+ pgd_quicklist = (unsigned long *)(*ret);
-+ ret[0] = 0;
-+ pgtable_cache_size--;
-+ } else
-+ ret = (unsigned long *)get_pgd_slow();
-+ return (pgd_t *)ret;
-+}
-+
-+static inline void free_pgd_fast(pgd_t *pgd)
-+{
-+ *(unsigned long *)pgd = (unsigned long) pgd_quicklist;
-+ pgd_quicklist = (unsigned long *) pgd;
-+ pgtable_cache_size++;
-+}
-+
-+static inline void free_pgd_slow(pgd_t *pgd)
-+{
-+ free_page((unsigned long)pgd);
-+}
-+
-+static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address)
-+{
-+ pte_t *pte;
-+
-+ pte = (pte_t *) __get_free_page(GFP_KERNEL);
-+ if (pte)
-+ clear_page(pte);
-+ return pte;
-+}
-+
-+static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long address)
-+{
-+ unsigned long *ret;
-+
-+ ret = (unsigned long *)pte_quicklist;
-+ if (ret != NULL) {
-+ pte_quicklist = (unsigned long *)(*ret);
-+ ret[0] = ret[1];
-+ pgtable_cache_size--;
-+ }
-+ return (pte_t *)ret;
-+}
-+
-+static inline void pte_free_fast(pte_t *pte)
-+{
-+ *(unsigned long *)pte = (unsigned long) pte_quicklist;
-+ pte_quicklist = (unsigned long *) pte;
-+ pgtable_cache_size++;
-+}
-+
-+static inline void pte_free_slow(pte_t *pte)
-+{
-+ free_page((unsigned long)pte);
-+}
-+
-+#define pte_free(pte) pte_free_fast(pte)
-+#define pgd_free(pgd) free_pgd_slow(pgd)
-+#define pgd_alloc(mm) get_pgd_fast()
-+
-+/*
-+ * allocating and freeing a pmd is trivial: the 1-entry pmd is
-+ * inside the pgd, so has no extra memory associated with it.
-+ */
-+
-+#define pmd_alloc_one_fast(mm, addr) ({ BUG(); ((pmd_t *)1); })
-+#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); })
-+#define pmd_free_slow(x) do { } while (0)
-+#define pmd_free_fast(x) do { } while (0)
-+#define pmd_free(x) do { } while (0)
-+#define pgd_populate(mm, pmd, pte) BUG()
-+
-+/*
-+ * TLB flushing:
-+ *
-+ * - flush_tlb() flushes the current mm struct TLBs
-+ * - flush_tlb_all() flushes all processes TLBs
-+ * - flush_tlb_mm(mm) flushes the specified mm context TLB's
-+ * - flush_tlb_page(vma, vmaddr) flushes one page
-+ * - flush_tlb_kernel_vm() flushes the kernel vm area
-+ * - flush_tlb_range(mm, start, end) flushes a range of pages
-+ * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
-+ */
-+
-+extern void flush_tlb_all(void);
-+extern void flush_tlb_mm(struct mm_struct *mm);
-+extern void flush_tlb_range(struct mm_struct *mm, unsigned long start,
-+ unsigned long end);
-+extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
-+extern void flush_tlb_kernel_vm(void);
-+
-+static inline void flush_tlb_pgtables(struct mm_struct *mm,
-+ unsigned long start, unsigned long end)
-+{
-+}
-+
-+#endif
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/include/asm-um/pgtable.h um/include/asm-um/pgtable.h
---- orig/include/asm-um/pgtable.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/pgtable.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,413 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Derived from include/asm-i386/pgtable.h
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UM_PGTABLE_H
-+#define __UM_PGTABLE_H
-+
-+#include "linux/sched.h"
-+#include "asm/processor.h"
-+#include "asm/page.h"
-+
-+extern pgd_t swapper_pg_dir[1024];
-+
-+#define flush_cache_all() do ; while (0)
-+#define flush_cache_mm(mm) do ; while (0)
-+#define flush_cache_range(vma, start, end) do ; while (0)
-+#define flush_cache_page(vma, vmaddr) do ; while (0)
-+#define flush_page_to_ram(page) do ; while (0)
-+#define flush_dcache_page(page) do ; while (0)
-+#define flush_icache_range(from, to) do ; while (0)
-+#define flush_icache_page(vma,pg) do ; while (0)
-+#define flush_icache_user_range(vma,pg,adr,len) do ; while (0)
-+
-+extern void __flush_tlb_one(unsigned long addr);
-+
-+extern void pte_free(pte_t *pte);
-+
-+extern void pgd_free(pgd_t *pgd);
-+
-+extern int do_check_pgt_cache(int, int);
-+
-+extern void *um_virt_to_phys(struct task_struct *task, unsigned long virt,
-+ pte_t *pte_out);
-+
-+/* zero page used for uninitialized stuff */
-+extern unsigned long *empty_zero_page;
-+
-+#define pgtable_cache_init() do ; while (0)
-+
-+/* PMD_SHIFT determines the size of the area a second-level page table can map */
-+#define PMD_SHIFT 22
-+#define PMD_SIZE (1UL << PMD_SHIFT)
-+#define PMD_MASK (~(PMD_SIZE-1))
-+
-+/* PGDIR_SHIFT determines what a third-level page table entry can map */
-+#define PGDIR_SHIFT 22
-+#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
-+#define PGDIR_MASK (~(PGDIR_SIZE-1))
-+
-+/*
-+ * entries per page directory level: the i386 is two-level, so
-+ * we don't really have any PMD directory physically.
-+ */
-+#define PTRS_PER_PTE 1024
-+#define PTRS_PER_PMD 1
-+#define PTRS_PER_PGD 1024
-+#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
-+#define FIRST_USER_PGD_NR 0
-+
-+#define pte_ERROR(e) \
-+ printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
-+#define pmd_ERROR(e) \
-+ printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
-+#define pgd_ERROR(e) \
-+ printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
-+
-+/*
-+ * pgd entries used up by user/kernel:
-+ */
-+
-+#define USER_PGD_PTRS (TASK_SIZE >> PGDIR_SHIFT)
-+#define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
-+
-+#ifndef __ASSEMBLY__
-+/* Just any arbitrary offset to the start of the vmalloc VM area: the
-+ * current 8MB value just means that there will be a 8MB "hole" after the
-+ * physical memory until the kernel virtual memory starts. That means that
-+ * any out-of-bounds memory accesses will hopefully be caught.
-+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
-+ * area for the same reason. ;)
-+ */
-+
-+extern unsigned long end_iomem;
-+
-+#define VMALLOC_OFFSET (__va_space)
-+#define VMALLOC_START ((end_iomem + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
-+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
-+
-+#if CONFIG_HIGHMEM
-+# define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE)
-+#else
-+# define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE)
-+#endif
-+
-+#define _PAGE_PRESENT 0x001
-+#define _PAGE_NEWPAGE 0x002
-+#define _PAGE_PROTNONE 0x004 /* If not present */
-+#define _PAGE_RW 0x008
-+#define _PAGE_USER 0x010
-+#define _PAGE_ACCESSED 0x020
-+#define _PAGE_DIRTY 0x040
-+#define _PAGE_NEWPROT 0x080
-+
-+#define REGION_MASK 0xf0000000
-+#define REGION_SHIFT 28
-+
-+#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
-+#define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
-+#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
-+
-+#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
-+#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
-+#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
-+#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
-+#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
-+#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_DIRTY | _PAGE_ACCESSED)
-+
-+/*
-+ * The i386 can't do page protection for execute, and considers that the same are read.
-+ * Also, write permissions imply read permissions. This is the closest we can get..
-+ */
-+#define __P000 PAGE_NONE
-+#define __P001 PAGE_READONLY
-+#define __P010 PAGE_COPY
-+#define __P011 PAGE_COPY
-+#define __P100 PAGE_READONLY
-+#define __P101 PAGE_READONLY
-+#define __P110 PAGE_COPY
-+#define __P111 PAGE_COPY
-+
-+#define __S000 PAGE_NONE
-+#define __S001 PAGE_READONLY
-+#define __S010 PAGE_SHARED
-+#define __S011 PAGE_SHARED
-+#define __S100 PAGE_READONLY
-+#define __S101 PAGE_READONLY
-+#define __S110 PAGE_SHARED
-+#define __S111 PAGE_SHARED
-+
-+/*
-+ * Define this if things work differently on an i386 and an i486:
-+ * it will (on an i486) warn about kernel memory accesses that are
-+ * done without a 'verify_area(VERIFY_WRITE,..)'
-+ */
-+#undef TEST_VERIFY_AREA
-+
-+/* page table for 0-4MB for everybody */
-+extern unsigned long pg0[1024];
-+
-+/*
-+ * BAD_PAGETABLE is used when we need a bogus page-table, while
-+ * BAD_PAGE is used for a bogus page.
-+ *
-+ * ZERO_PAGE is a global shared page that is always zero: used
-+ * for zero-mapped memory areas etc..
-+ */
-+extern pte_t __bad_page(void);
-+extern pte_t * __bad_pagetable(void);
-+
-+#define BAD_PAGETABLE __bad_pagetable()
-+#define BAD_PAGE __bad_page()
-+
-+#define ZERO_PAGE(vaddr) virt_to_page(empty_zero_page)
-+
-+/* number of bits that fit into a memory pointer */
-+#define BITS_PER_PTR (8*sizeof(unsigned long))
-+
-+/* to align the pointer to a pointer address */
-+#define PTR_MASK (~(sizeof(void*)-1))
-+
-+/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
-+/* 64-bit machines, beware! SRB. */
-+#define SIZEOF_PTR_LOG2 2
-+
-+/* to find an entry in a page-table */
-+#define PAGE_PTR(address) \
-+((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
-+
-+#define pte_none(x) !(pte_val(x) & ~_PAGE_NEWPAGE)
-+#define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE))
-+
-+#define pte_clear(xp) do { pte_val(*(xp)) = _PAGE_NEWPAGE; } while (0)
-+
-+#define pmd_none(x) (!(pmd_val(x) & ~_PAGE_NEWPAGE))
-+#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
-+#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
-+#define pmd_clear(xp) do { pmd_val(*(xp)) = _PAGE_NEWPAGE; } while (0)
-+
-+#define pmd_newpage(x) (pmd_val(x) & _PAGE_NEWPAGE)
-+#define pmd_mkuptodate(x) (pmd_val(x) &= ~_PAGE_NEWPAGE)
-+
-+/*
-+ * The "pgd_xxx()" functions here are trivial for a folded two-level
-+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
-+ * into the pgd entry)
-+ */
-+static inline int pgd_none(pgd_t pgd) { return 0; }
-+static inline int pgd_bad(pgd_t pgd) { return 0; }
-+static inline int pgd_present(pgd_t pgd) { return 1; }
-+static inline void pgd_clear(pgd_t * pgdp) { }
-+
-+#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
-+
-+#define pte_page(pte) virt_to_page(__va(pte_val(pte)))
-+#define pmd_page(pmd) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
-+
-+extern struct page *phys_to_page(const unsigned long phys);
-+extern struct page *__virt_to_page(const unsigned long virt);
-+#define virt_to_page(addr) __virt_to_page((const unsigned long) addr)
-+
-+static inline pte_t pte_mknewprot(pte_t pte)
-+{
-+ pte_val(pte) |= _PAGE_NEWPROT;
-+ return(pte);
-+}
-+
-+static inline pte_t pte_mknewpage(pte_t pte)
-+{
-+ pte_val(pte) |= _PAGE_NEWPAGE;
-+ return(pte);
-+}
-+
-+static inline void set_pte(pte_t *pteptr, pte_t pteval)
-+{
-+ /* If it's a swap entry, it needs to be marked _PAGE_NEWPAGE so
-+ * fix_range knows to unmap it. _PAGE_NEWPROT is specific to
-+ * mapped pages.
-+ */
-+ *pteptr = pte_mknewpage(pteval);
-+ if(pte_present(*pteptr)) *pteptr = pte_mknewprot(*pteptr);
-+}
-+
-+/*
-+ * (pmds are folded into pgds so this doesnt get actually called,
-+ * but the define is needed for a generic inline function.)
-+ */
-+#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval)
-+#define set_pgd(pgdptr, pgdval) (*(pgdptr) = pgdval)
-+
-+/*
-+ * The following only work if pte_present() is true.
-+ * Undefined behaviour if not..
-+ */
-+static inline int pte_read(pte_t pte)
-+{
-+ return((pte_val(pte) & _PAGE_USER) &&
-+ !(pte_val(pte) & _PAGE_PROTNONE));
-+}
-+
-+static inline int pte_exec(pte_t pte){
-+ return((pte_val(pte) & _PAGE_USER) &&
-+ !(pte_val(pte) & _PAGE_PROTNONE));
-+}
-+
-+static inline int pte_write(pte_t pte)
-+{
-+ return((pte_val(pte) & _PAGE_RW) &&
-+ !(pte_val(pte) & _PAGE_PROTNONE));
-+}
-+
-+static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
-+static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
-+static inline int pte_newpage(pte_t pte) { return pte_val(pte) & _PAGE_NEWPAGE; }
-+static inline int pte_newprot(pte_t pte)
-+{
-+ return(pte_present(pte) && (pte_val(pte) & _PAGE_NEWPROT));
-+}
-+
-+static inline pte_t pte_rdprotect(pte_t pte)
-+{
-+ pte_val(pte) &= ~_PAGE_USER;
-+ return(pte_mknewprot(pte));
-+}
-+
-+static inline pte_t pte_exprotect(pte_t pte)
-+{
-+ pte_val(pte) &= ~_PAGE_USER;
-+ return(pte_mknewprot(pte));
-+}
-+
-+static inline pte_t pte_mkclean(pte_t pte)
-+{
-+ pte_val(pte) &= ~_PAGE_DIRTY;
-+ return(pte);
-+}
-+
-+static inline pte_t pte_mkold(pte_t pte)
-+{
-+ pte_val(pte) &= ~_PAGE_ACCESSED;
-+ return(pte);
-+}
-+
-+static inline pte_t pte_wrprotect(pte_t pte)
-+{
-+ pte_val(pte) &= ~_PAGE_RW;
-+ return(pte_mknewprot(pte));
-+}
-+
-+static inline pte_t pte_mkread(pte_t pte)
-+{
-+ pte_val(pte) |= _PAGE_USER;
-+ return(pte_mknewprot(pte));
-+}
-+
-+static inline pte_t pte_mkexec(pte_t pte)
-+{
-+ pte_val(pte) |= _PAGE_USER;
-+ return(pte_mknewprot(pte));
-+}
-+
-+static inline pte_t pte_mkdirty(pte_t pte)
-+{
-+ pte_val(pte) |= _PAGE_DIRTY;
-+ return(pte);
-+}
-+
-+static inline pte_t pte_mkyoung(pte_t pte)
-+{
-+ pte_val(pte) |= _PAGE_ACCESSED;
-+ return(pte);
-+}
-+
-+static inline pte_t pte_mkwrite(pte_t pte)
-+{
-+ pte_val(pte) |= _PAGE_RW;
-+ return(pte_mknewprot(pte));
-+}
-+
-+static inline pte_t pte_mkuptodate(pte_t pte)
-+{
-+ pte_val(pte) &= ~_PAGE_NEWPAGE;
-+ if(pte_present(pte)) pte_val(pte) &= ~_PAGE_NEWPROT;
-+ return(pte);
-+}
-+
-+extern unsigned long page_to_phys(struct page *page);
-+
-+/*
-+ * Conversion functions: convert a page and protection to a page entry,
-+ * and a page entry and page directory to the page they refer to.
-+ */
-+
-+extern pte_t mk_pte(struct page *page, pgprot_t pgprot);
-+
-+/* This takes a physical page address that is used by the remapping
-+ * functions
-+ */
-+#define mk_pte_phys(phys, pgprot) \
-+ (pte_mknewpage(mk_pte(virt_to_page(__va(phys)), pgprot)))
-+
-+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
-+{
-+ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
-+ if(pte_present(pte)) pte = pte_mknewpage(pte_mknewprot(pte));
-+ return pte;
-+}
-+
-+/* to find an entry in a page-table-directory. */
-+#define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
-+#define __pgd_offset(address) pgd_index(address)
-+
-+/* to find an entry in a page-table-directory */
-+#define pgd_offset(mm, address) \
-+((mm)->pgd + ((address) >> PGDIR_SHIFT))
-+
-+/* to find an entry in a kernel page-table-directory */
-+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
-+
-+#define __pmd_offset(address) \
-+ (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
-+
-+/* Find an entry in the second-level page table.. */
-+static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
-+{
-+ return (pmd_t *) dir;
-+}
-+
-+/* Find an entry in the third-level page table.. */
-+#define pte_offset(pmd, address) \
-+ ((pte_t *) (pmd_page(*pmd) + ((address>>10) & ((PTRS_PER_PTE-1)<<2))))
-+
-+#define update_mmu_cache(vma,address,pte) do ; while (0)
-+
-+/* Encode and de-code a swap entry */
-+#define SWP_TYPE(x) (((x).val >> 3) & 0x7f)
-+#define SWP_OFFSET(x) ((x).val >> 10)
-+
-+#define SWP_ENTRY(type, offset) \
-+ ((swp_entry_t) { ((type) << 3) | ((offset) << 10) })
-+#define pte_to_swp_entry(pte) \
-+ ((swp_entry_t) { pte_val(pte_mkuptodate(pte)) })
-+#define swp_entry_to_pte(x) ((pte_t) { (x).val })
-+
-+#define PageSkip(x) (0)
-+#define kern_addr_valid(addr) (1)
-+
-+#include <asm-generic/pgtable.h>
-+
-+#endif
-+
-+#endif
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/include/asm-um/poll.h um/include/asm-um/poll.h
---- orig/include/asm-um/poll.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/poll.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_POLL_H
-+#define __UM_POLL_H
-+
-+#include "asm/arch/poll.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/posix_types.h um/include/asm-um/posix_types.h
---- orig/include/asm-um/posix_types.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/posix_types.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_POSIX_TYPES_H
-+#define __UM_POSIX_TYPES_H
-+
-+#include "asm/arch/posix_types.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/processor-generic.h um/include/asm-um/processor-generic.h
---- orig/include/asm-um/processor-generic.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/processor-generic.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,177 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UM_PROCESSOR_GENERIC_H
-+#define __UM_PROCESSOR_GENERIC_H
-+
-+struct pt_regs;
-+
-+struct task_struct;
-+
-+#include "linux/config.h"
-+#include "linux/signal.h"
-+#include "asm/ptrace.h"
-+#include "asm/siginfo.h"
-+#include "choose-mode.h"
-+
-+struct mm_struct;
-+
-+#define current_text_addr() ((void *) 0)
-+
-+#define cpu_relax() do ; while (0)
-+
-+struct thread_struct {
-+ int forking;
-+ unsigned long kernel_stack;
-+ int nsyscalls;
-+ struct pt_regs regs;
-+ unsigned long cr2;
-+ int err;
-+ unsigned long trap_no;
-+ void *fault_addr;
-+ void *fault_catcher;
-+ struct task_struct *prev_sched;
-+ unsigned long temp_stack;
-+ void *exec_buf;
-+ struct arch_thread arch;
-+ union {
-+#ifdef CONFIG_MODE_TT
-+ struct {
-+ int extern_pid;
-+ int tracing;
-+ int switch_pipe[2];
-+ int singlestep_syscall;
-+ int vm_seq;
-+ } tt;
-+#endif
-+#ifdef CONFIG_MODE_SKAS
-+ struct {
-+ void *switch_buf;
-+ void *fork_buf;
-+ int mm_count;
-+ } skas;
-+#endif
-+ } mode;
-+ struct {
-+ int op;
-+ union {
-+ struct {
-+ int pid;
-+ } fork, exec;
-+ struct {
-+ int (*proc)(void *);
-+ void *arg;
-+ } thread;
-+ struct {
-+ void (*proc)(void *);
-+ void *arg;
-+ } cb;
-+ } u;
-+ } request;
-+};
-+
-+#define INIT_THREAD \
-+{ \
-+ .forking = 0, \
-+ .kernel_stack = 0, \
-+ .nsyscalls = 0, \
-+ .regs = EMPTY_REGS, \
-+ .cr2 = 0, \
-+ .err = 0, \
-+ .fault_addr = NULL, \
-+ .prev_sched = NULL, \
-+ .temp_stack = 0, \
-+ .exec_buf = NULL, \
-+ .arch = INIT_ARCH_THREAD, \
-+ .request = { 0 } \
-+}
-+
-+#define THREAD_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE)
-+
-+typedef struct {
-+ unsigned long seg;
-+} mm_segment_t;
-+
-+extern struct task_struct *alloc_task_struct(void);
-+extern void free_task_struct(struct task_struct *task);
-+
-+#define get_task_struct(tsk) atomic_inc(&virt_to_page(tsk)->count)
-+
-+extern void release_thread(struct task_struct *);
-+extern int arch_kernel_thread(int (*fn)(void *), void * arg,
-+ unsigned long flags);
-+extern void dump_thread(struct pt_regs *regs, struct user *u);
-+
-+extern unsigned long thread_saved_pc(struct thread_struct *t);
-+
-+static inline void mm_copy_segments(struct mm_struct *from_mm,
-+ struct mm_struct *new_mm)
-+{
-+}
-+
-+static inline void copy_segments(struct task_struct *p,
-+ struct mm_struct *new_mm)
-+{
-+}
-+
-+static inline void release_segments(struct mm_struct *mm)
-+{
-+}
-+
-+#define init_task (init_task_union.task)
-+#define init_stack (init_task_union.stack)
-+
-+/*
-+ * User space process size: 3GB (default).
-+ */
-+extern unsigned long task_size;
-+
-+#define TASK_SIZE (task_size)
-+
-+/* This decides where the kernel will search for a free chunk of vm
-+ * space during mmap's.
-+ */
-+#define TASK_UNMAPPED_BASE (0x40000000)
-+
-+extern void start_thread(struct pt_regs *regs, unsigned long entry,
-+ unsigned long stack);
-+
-+struct cpuinfo_um {
-+ unsigned long loops_per_jiffy;
-+ unsigned long *pgd_quick;
-+ unsigned long *pmd_quick;
-+ unsigned long *pte_quick;
-+ unsigned long pgtable_cache_sz;
-+ int ipi_pipe[2];
-+};
-+
-+extern struct cpuinfo_um boot_cpu_data;
-+
-+#define my_cpu_data cpu_data[smp_processor_id()]
-+
-+#ifdef CONFIG_SMP
-+extern struct cpuinfo_um cpu_data[];
-+#define current_cpu_data cpu_data[smp_processor_id()]
-+#else
-+#define cpu_data (&boot_cpu_data)
-+#define current_cpu_data boot_cpu_data
-+#endif
-+
-+#define KSTK_EIP(tsk) (PT_REGS_IP(&tsk->thread.regs))
-+#define KSTK_ESP(tsk) (PT_REGS_SP(&tsk->thread.regs))
-+#define get_wchan(p) (0)
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/include/asm-um/processor-i386.h um/include/asm-um/processor-i386.h
---- orig/include/asm-um/processor-i386.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/processor-i386.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,35 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UM_PROCESSOR_I386_H
-+#define __UM_PROCESSOR_I386_H
-+
-+extern int cpu_has_xmm;
-+extern int cpu_has_cmov;
-+
-+struct arch_thread {
-+ unsigned long debugregs[8];
-+ int debugregs_seq;
-+};
-+
-+#define INIT_ARCH_THREAD { .debugregs = { [ 0 ... 7 ] = 0 }, \
-+ .debugregs_seq = 0 }
-+
-+#include "asm/arch/user.h"
-+
-+#include "asm/processor-generic.h"
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/include/asm-um/processor-ppc.h um/include/asm-um/processor-ppc.h
---- orig/include/asm-um/processor-ppc.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/processor-ppc.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,15 @@
-+#ifndef __UM_PROCESSOR_PPC_H
-+#define __UM_PROCESSOR_PPC_H
-+
-+#if defined(__ASSEMBLY__)
-+
-+#define CONFIG_ALL_PPC
-+#include "arch/processor.h"
-+
-+#else
-+
-+#include "asm/processor-generic.h"
-+
-+#endif
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/ptrace-generic.h um/include/asm-um/ptrace-generic.h
---- orig/include/asm-um/ptrace-generic.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/ptrace-generic.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,74 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UM_PTRACE_GENERIC_H
-+#define __UM_PTRACE_GENERIC_H
-+
-+#ifndef __ASSEMBLY__
-+
-+#include "linux/config.h"
-+
-+#include "asm/current.h"
-+
-+#define pt_regs pt_regs_subarch
-+#define show_regs show_regs_subarch
-+
-+#include "asm/arch/ptrace.h"
-+
-+#undef pt_regs
-+#undef show_regs
-+#undef user_mode
-+#undef instruction_pointer
-+
-+#include "sysdep/ptrace.h"
-+#include "skas_ptrace.h"
-+
-+struct pt_regs {
-+ union uml_pt_regs regs;
-+};
-+
-+#define EMPTY_REGS { regs : EMPTY_UML_PT_REGS }
-+
-+#define PT_REGS_IP(r) UPT_IP(&(r)->regs)
-+#define PT_REGS_SP(r) UPT_SP(&(r)->regs)
-+
-+#define PT_REG(r, reg) UPT_REG(&(r)->regs, reg)
-+#define PT_REGS_SET(r, reg, val) UPT_SET(&(r)->regs, reg, val)
-+
-+#define PT_REGS_SET_SYSCALL_RETURN(r, res) \
-+ UPT_SET_SYSCALL_RETURN(&(r)->regs, res)
-+#define PT_REGS_RESTART_SYSCALL(r) UPT_RESTART_SYSCALL(&(r)->regs)
-+
-+#define PT_REGS_SYSCALL_NR(r) UPT_SYSCALL_NR(&(r)->regs)
-+
-+#define PT_REGS_SC(r) UPT_SC(&(r)->regs)
-+
-+struct task_struct;
-+
-+extern unsigned long getreg(struct task_struct *child, int regno);
-+extern int putreg(struct task_struct *child, int regno, unsigned long value);
-+extern int get_fpregs(unsigned long buf, struct task_struct *child);
-+extern int set_fpregs(unsigned long buf, struct task_struct *child);
-+extern int get_fpxregs(unsigned long buf, struct task_struct *child);
-+extern int set_fpxregs(unsigned long buf, struct task_struct *tsk);
-+
-+extern void show_regs(struct pt_regs *regs);
-+
-+#define INIT_TASK_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE)
-+
-+#endif
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/include/asm-um/ptrace-i386.h um/include/asm-um/ptrace-i386.h
---- orig/include/asm-um/ptrace-i386.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/ptrace-i386.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,46 @@
-+/*
-+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UM_PTRACE_I386_H
-+#define __UM_PTRACE_I386_H
-+
-+#include "sysdep/ptrace.h"
-+#include "asm/ptrace-generic.h"
-+
-+#define PT_REGS_EAX(r) UPT_EAX(&(r)->regs)
-+#define PT_REGS_EBX(r) UPT_EBX(&(r)->regs)
-+#define PT_REGS_ECX(r) UPT_ECX(&(r)->regs)
-+#define PT_REGS_EDX(r) UPT_EDX(&(r)->regs)
-+#define PT_REGS_ESI(r) UPT_ESI(&(r)->regs)
-+#define PT_REGS_EDI(r) UPT_EDI(&(r)->regs)
-+#define PT_REGS_EBP(r) UPT_EBP(&(r)->regs)
-+
-+#define PT_REGS_CS(r) UPT_CS(&(r)->regs)
-+#define PT_REGS_SS(r) UPT_SS(&(r)->regs)
-+#define PT_REGS_DS(r) UPT_DS(&(r)->regs)
-+#define PT_REGS_ES(r) UPT_ES(&(r)->regs)
-+#define PT_REGS_FS(r) UPT_FS(&(r)->regs)
-+#define PT_REGS_GS(r) UPT_GS(&(r)->regs)
-+
-+#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs)
-+
-+#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_EAX(r)
-+#define PT_REGS_SYSCALL_RET(r) PT_REGS_EAX(r)
-+#define PT_FIX_EXEC_STACK(sp) do ; while(0)
-+
-+#define user_mode(r) UPT_IS_USER(&(r)->regs)
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/include/asm-um/resource.h um/include/asm-um/resource.h
---- orig/include/asm-um/resource.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/resource.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_RESOURCE_H
-+#define __UM_RESOURCE_H
-+
-+#include "asm/arch/resource.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/rwlock.h um/include/asm-um/rwlock.h
---- orig/include/asm-um/rwlock.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/rwlock.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_RWLOCK_H
-+#define __UM_RWLOCK_H
-+
-+#include "asm/arch/rwlock.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/rwsem.h um/include/asm-um/rwsem.h
---- orig/include/asm-um/rwsem.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/rwsem.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,10 @@
-+#ifndef __UM_RWSEM_H__
-+#define __UM_RWSEM_H__
-+
-+#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
-+#define __builtin_expect(exp,c) (exp)
-+#endif
-+
-+#include "asm/arch/rwsem.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/scatterlist.h um/include/asm-um/scatterlist.h
---- orig/include/asm-um/scatterlist.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/scatterlist.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_SCATTERLIST_H
-+#define __UM_SCATTERLIST_H
-+
-+#include "asm/arch/scatterlist.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/segment.h um/include/asm-um/segment.h
---- orig/include/asm-um/segment.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/segment.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,4 @@
-+#ifndef __UM_SEGMENT_H
-+#define __UM_SEGMENT_H
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/semaphore.h um/include/asm-um/semaphore.h
---- orig/include/asm-um/semaphore.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/semaphore.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,6 @@
-+#ifndef __UM_SEMAPHORE_H
-+#define __UM_SEMAPHORE_H
-+
-+#include "asm/arch/semaphore.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/sembuf.h um/include/asm-um/sembuf.h
---- orig/include/asm-um/sembuf.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/sembuf.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_SEMBUF_H
-+#define __UM_SEMBUF_H
-+
-+#include "asm/arch/sembuf.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/serial.h um/include/asm-um/serial.h
---- orig/include/asm-um/serial.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/serial.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_SERIAL_H
-+#define __UM_SERIAL_H
-+
-+#include "asm/arch/serial.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/shmbuf.h um/include/asm-um/shmbuf.h
---- orig/include/asm-um/shmbuf.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/shmbuf.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_SHMBUF_H
-+#define __UM_SHMBUF_H
-+
-+#include "asm/arch/shmbuf.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/shmparam.h um/include/asm-um/shmparam.h
---- orig/include/asm-um/shmparam.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/shmparam.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_SHMPARAM_H
-+#define __UM_SHMPARAM_H
-+
-+#include "asm/arch/shmparam.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/sigcontext-generic.h um/include/asm-um/sigcontext-generic.h
---- orig/include/asm-um/sigcontext-generic.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/sigcontext-generic.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_SIGCONTEXT_GENERIC_H
-+#define __UM_SIGCONTEXT_GENERIC_H
-+
-+#include "asm/arch/sigcontext.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/sigcontext-i386.h um/include/asm-um/sigcontext-i386.h
---- orig/include/asm-um/sigcontext-i386.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/sigcontext-i386.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_SIGCONTEXT_I386_H
-+#define __UM_SIGCONTEXT_I386_H
-+
-+#include "asm/sigcontext-generic.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/sigcontext-ppc.h um/include/asm-um/sigcontext-ppc.h
---- orig/include/asm-um/sigcontext-ppc.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/sigcontext-ppc.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,10 @@
-+#ifndef __UM_SIGCONTEXT_PPC_H
-+#define __UM_SIGCONTEXT_PPC_H
-+
-+#define pt_regs sys_pt_regs
-+
-+#include "asm/sigcontext-generic.h"
-+
-+#undef pt_regs
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/siginfo.h um/include/asm-um/siginfo.h
---- orig/include/asm-um/siginfo.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/siginfo.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,6 @@
-+#ifndef __UM_SIGINFO_H
-+#define __UM_SIGINFO_H
-+
-+#include "asm/arch/siginfo.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/signal.h um/include/asm-um/signal.h
---- orig/include/asm-um/signal.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/signal.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,22 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UM_SIGNAL_H
-+#define __UM_SIGNAL_H
-+
-+#include "asm/arch/signal.h"
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/include/asm-um/smp.h um/include/asm-um/smp.h
---- orig/include/asm-um/smp.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/smp.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,19 @@
-+#ifndef __UM_SMP_H
-+#define __UM_SMP_H
-+
-+#ifdef CONFIG_SMP
-+
-+#include "linux/config.h"
-+#include "asm/current.h"
-+
-+#define smp_processor_id() (current->processor)
-+#define cpu_logical_map(n) (n)
-+#define cpu_number_map(n) (n)
-+#define PROC_CHANGE_PENALTY 15 /* Pick a number, any number */
-+extern int hard_smp_processor_id(void);
-+extern unsigned long cpu_online_map;
-+#define NO_PROC_ID -1
-+
-+#endif
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/smplock.h um/include/asm-um/smplock.h
---- orig/include/asm-um/smplock.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/smplock.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,6 @@
-+#ifndef __UM_SMPLOCK_H
-+#define __UM_SMPLOCK_H
-+
-+#include "asm/arch/smplock.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/socket.h um/include/asm-um/socket.h
---- orig/include/asm-um/socket.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/socket.h 2003-11-07 02:10:43.000000000 -0500
-@@ -0,0 +1,6 @@
-+#ifndef __UM_SOCKET_H
-+#define __UM_SOCKET_H
-+
-+#include "asm/arch/socket.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/sockios.h um/include/asm-um/sockios.h
---- orig/include/asm-um/sockios.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/sockios.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_SOCKIOS_H
-+#define __UM_SOCKIOS_H
-+
-+#include "asm/arch/sockios.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/softirq.h um/include/asm-um/softirq.h
---- orig/include/asm-um/softirq.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/softirq.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,13 @@
-+#ifndef __UM_SOFTIRQ_H
-+#define __UM_SOFTIRQ_H
-+
-+#include "linux/smp.h"
-+#include "asm/system.h"
-+#include "asm/processor.h"
-+
-+/* A gratuitous name change */
-+#define i386_bh_lock um_bh_lock
-+#include "asm/arch/softirq.h"
-+#undef i386_bh_lock
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/spinlock.h um/include/asm-um/spinlock.h
---- orig/include/asm-um/spinlock.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/spinlock.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,10 @@
-+#ifndef __UM_SPINLOCK_H
-+#define __UM_SPINLOCK_H
-+
-+#include "linux/config.h"
-+
-+#ifdef CONFIG_SMP
-+#include "asm/arch/spinlock.h"
-+#endif
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/statfs.h um/include/asm-um/statfs.h
---- orig/include/asm-um/statfs.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/statfs.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,6 @@
-+#ifndef _UM_STATFS_H
-+#define _UM_STATFS_H
-+
-+#include "asm/arch/statfs.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/stat.h um/include/asm-um/stat.h
---- orig/include/asm-um/stat.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/stat.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_STAT_H
-+#define __UM_STAT_H
-+
-+#include "asm/arch/stat.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/string.h um/include/asm-um/string.h
---- orig/include/asm-um/string.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/string.h 2004-01-16 03:32:58.000000000 -0500
-@@ -0,0 +1,7 @@
-+#ifndef __UM_STRING_H
-+#define __UM_STRING_H
-+
-+#include "asm/arch/string.h"
-+#include "asm/archparam.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/system-generic.h um/include/asm-um/system-generic.h
---- orig/include/asm-um/system-generic.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/system-generic.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,50 @@
-+#ifndef __UM_SYSTEM_GENERIC_H
-+#define __UM_SYSTEM_GENERIC_H
-+
-+#include "asm/arch/system.h"
-+
-+#undef prepare_to_switch
-+#undef switch_to
-+#undef __save_flags
-+#undef save_flags
-+#undef __restore_flags
-+#undef restore_flags
-+#undef __cli
-+#undef __sti
-+#undef cli
-+#undef sti
-+#undef local_irq_save
-+#undef local_irq_restore
-+#undef local_irq_disable
-+#undef local_irq_enable
-+
-+#define prepare_to_switch() do ; while(0)
-+
-+void *_switch_to(void *prev, void *next);
-+
-+#define switch_to(prev, next, last) prev = _switch_to(prev, next)
-+
-+extern int get_signals(void);
-+extern int set_signals(int enable);
-+extern void block_signals(void);
-+extern void unblock_signals(void);
-+
-+#define local_irq_save(flags) do { (flags) = set_signals(0); } while(0)
-+
-+#define local_irq_restore(flags) do { set_signals(flags); } while(0)
-+
-+#define local_irq_enable() unblock_signals()
-+#define local_irq_disable() block_signals()
-+
-+#define __sti() unblock_signals()
-+#define sti() unblock_signals()
-+#define __cli() block_signals()
-+#define cli() block_signals()
-+
-+#define __save_flags(x) do { (x) = get_signals(); } while(0)
-+#define save_flags(x) __save_flags(x)
-+
-+#define __restore_flags(x) local_irq_restore(x)
-+#define restore_flags(x) __restore_flags(x)
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/system-i386.h um/include/asm-um/system-i386.h
---- orig/include/asm-um/system-i386.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/system-i386.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,39 @@
-+#ifndef __UM_SYSTEM_I386_H
-+#define __UM_SYSTEM_I386_H
-+
-+#include "asm/system-generic.h"
-+
-+#define __HAVE_ARCH_CMPXCHG 1
-+
-+static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
-+ unsigned long new, int size)
-+{
-+ unsigned long prev;
-+ switch (size) {
-+ case 1:
-+ __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
-+ : "=a"(prev)
-+ : "q"(new), "m"(*__xg(ptr)), "0"(old)
-+ : "memory");
-+ return prev;
-+ case 2:
-+ __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
-+ : "=a"(prev)
-+ : "q"(new), "m"(*__xg(ptr)), "0"(old)
-+ : "memory");
-+ return prev;
-+ case 4:
-+ __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
-+ : "=a"(prev)
-+ : "q"(new), "m"(*__xg(ptr)), "0"(old)
-+ : "memory");
-+ return prev;
-+ }
-+ return old;
-+}
-+
-+#define cmpxchg(ptr,o,n)\
-+ ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
-+ (unsigned long)(n),sizeof(*(ptr))))
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/system-ppc.h um/include/asm-um/system-ppc.h
---- orig/include/asm-um/system-ppc.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/system-ppc.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,12 @@
-+#ifndef __UM_SYSTEM_PPC_H
-+#define __UM_SYSTEM_PPC_H
-+
-+#define _switch_to _ppc_switch_to
-+
-+#include "asm/arch/system.h"
-+
-+#undef _switch_to
-+
-+#include "asm/system-generic.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/termbits.h um/include/asm-um/termbits.h
---- orig/include/asm-um/termbits.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/termbits.h 2003-11-07 02:10:43.000000000 -0500
-@@ -0,0 +1,6 @@
-+#ifndef __UM_TERMBITS_H
-+#define __UM_TERMBITS_H
-+
-+#include "asm/arch/termbits.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/termios.h um/include/asm-um/termios.h
---- orig/include/asm-um/termios.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/termios.h 2003-12-16 22:26:55.000000000 -0500
-@@ -0,0 +1,6 @@
-+#ifndef __UM_TERMIOS_H
-+#define __UM_TERMIOS_H
-+
-+#include "asm/arch/termios.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/timex.h um/include/asm-um/timex.h
---- orig/include/asm-um/timex.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/timex.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,18 @@
-+#ifndef __UM_TIMEX_H
-+#define __UM_TIMEX_H
-+
-+#include "linux/time.h"
-+
-+typedef unsigned long cycles_t;
-+
-+#define cacheflush_time (0)
-+
-+static inline cycles_t get_cycles (void)
-+{
-+ return 0;
-+}
-+
-+#define vxtime_lock() do ; while (0)
-+#define vxtime_unlock() do ; while (0)
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/tlb.h um/include/asm-um/tlb.h
---- orig/include/asm-um/tlb.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/tlb.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1 @@
-+#include <asm-generic/tlb.h>
-diff -Naur -X ../exclude-files orig/include/asm-um/types.h um/include/asm-um/types.h
---- orig/include/asm-um/types.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/types.h 2004-01-16 03:32:58.000000000 -0500
-@@ -0,0 +1,6 @@
-+#ifndef __UM_TYPES_H
-+#define __UM_TYPES_H
-+
-+#include "asm/arch/types.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/uaccess.h um/include/asm-um/uaccess.h
---- orig/include/asm-um/uaccess.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/uaccess.h 2004-02-14 06:28:59.000000000 -0500
-@@ -0,0 +1,99 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __UM_UACCESS_H
-+#define __UM_UACCESS_H
-+
-+#include "linux/sched.h"
-+
-+#define VERIFY_READ 0
-+#define VERIFY_WRITE 1
-+
-+/*
-+ * The fs value determines whether argument validity checking should be
-+ * performed or not. If get_fs() == USER_DS, checking is performed, with
-+ * get_fs() == KERNEL_DS, checking is bypassed.
-+ *
-+ * For historical reasons, these macros are grossly misnamed.
-+ */
-+
-+#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
-+
-+#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF)
-+#define USER_DS MAKE_MM_SEG(TASK_SIZE)
-+
-+#define get_ds() (KERNEL_DS)
-+#define get_fs() (current->addr_limit)
-+#define set_fs(x) (current->addr_limit = (x))
-+
-+#define segment_eq(a, b) ((a).seg == (b).seg)
-+
-+#include "um_uaccess.h"
-+
-+#define __copy_from_user(to, from, n) copy_from_user(to, from, n)
-+
-+#define __copy_to_user(to, from, n) copy_to_user(to, from, n)
-+
-+#define __get_user(x, ptr) \
-+({ \
-+ const __typeof__(ptr) __private_ptr = ptr; \
-+ __typeof__(*(__private_ptr)) __private_val; \
-+ int __private_ret = -EFAULT; \
-+ (x) = 0; \
-+ if (__copy_from_user(&__private_val, (__private_ptr), \
-+ sizeof(*(__private_ptr))) == 0) {\
-+ (x) = (__typeof__(*(__private_ptr))) __private_val; \
-+ __private_ret = 0; \
-+ } \
-+ __private_ret; \
-+})
-+
-+#define get_user(x, ptr) \
-+({ \
-+ const __typeof__((*ptr)) *private_ptr = (ptr); \
-+ (access_ok(VERIFY_READ, private_ptr, sizeof(*private_ptr)) ? \
-+ __get_user(x, private_ptr) : ((x) = 0, -EFAULT)); \
-+})
-+
-+#define __put_user(x, ptr) \
-+({ \
-+ __typeof__(ptr) __private_ptr = ptr; \
-+ __typeof__(*(__private_ptr)) __private_val; \
-+ int __private_ret = -EFAULT; \
-+ __private_val = (__typeof__(*(__private_ptr))) (x); \
-+ if (__copy_to_user((__private_ptr), &__private_val, \
-+ sizeof(*(__private_ptr))) == 0) { \
-+ __private_ret = 0; \
-+ } \
-+ __private_ret; \
-+})
-+
-+#define put_user(x, ptr) \
-+({ \
-+ __typeof__(*(ptr)) *private_ptr = (ptr); \
-+ (access_ok(VERIFY_WRITE, private_ptr, sizeof(*private_ptr)) ? \
-+ __put_user(x, private_ptr) : -EFAULT); \
-+})
-+
-+#define strlen_user(str) strnlen_user(str, ~0UL >> 1)
-+
-+struct exception_table_entry
-+{
-+ unsigned long insn;
-+ unsigned long fixup;
-+};
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/include/asm-um/ucontext.h um/include/asm-um/ucontext.h
---- orig/include/asm-um/ucontext.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/ucontext.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef _ASM_UM_UCONTEXT_H
-+#define _ASM_UM_UCONTEXT_H
-+
-+#include "asm/arch/ucontext.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/unaligned.h um/include/asm-um/unaligned.h
---- orig/include/asm-um/unaligned.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/unaligned.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_UNALIGNED_H
-+#define __UM_UNALIGNED_H
-+
-+#include "asm/arch/unaligned.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/unistd.h um/include/asm-um/unistd.h
---- orig/include/asm-um/unistd.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/unistd.h 2004-02-14 06:29:00.000000000 -0500
-@@ -0,0 +1,121 @@
-+/*
-+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef _UM_UNISTD_H_
-+#define _UM_UNISTD_H_
-+
-+#include "linux/resource.h"
-+#include "asm/uaccess.h"
-+
-+extern long sys_open(const char *filename, int flags, int mode);
-+extern long sys_dup(unsigned int fildes);
-+extern long sys_close(unsigned int fd);
-+extern int um_execve(const char *file, char *const argv[], char *const env[]);
-+extern long sys_setsid(void);
-+extern long sys_waitpid(pid_t pid, unsigned int * stat_addr, int options);
-+extern long sys_wait4(pid_t pid,unsigned int *stat_addr, int options,
-+ struct rusage *ru);
-+extern long sys_mount(char *dev_name, char *dir_name, char *type,
-+ unsigned long flags, void *data);
-+extern long sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp,
-+ struct timeval *tvp);
-+extern long sys_lseek(unsigned int fildes, unsigned long offset, int whence);
-+extern long sys_read(unsigned int fildes, char *buf, int len);
-+extern long sys_write(unsigned int fildes, char *buf, int len);
-+
-+#ifdef __KERNEL_SYSCALLS__
-+
-+#define KERNEL_CALL(ret_t, sys, args...) \
-+ mm_segment_t fs = get_fs(); \
-+ ret_t ret; \
-+ set_fs(KERNEL_DS); \
-+ ret = sys(args); \
-+ set_fs(fs); \
-+ if (ret >= 0) \
-+ return ret; \
-+ errno = -(long)ret; \
-+ return -1;
-+
-+static inline long open(const char *pathname, int flags, int mode)
-+{
-+ KERNEL_CALL(int, sys_open, pathname, flags, mode)
-+}
-+
-+static inline long dup(unsigned int fd)
-+{
-+ KERNEL_CALL(int, sys_dup, fd);
-+}
-+
-+static inline long close(unsigned int fd)
-+{
-+ KERNEL_CALL(int, sys_close, fd);
-+}
-+
-+static inline int execve(const char *filename, char *const argv[],
-+ char *const envp[])
-+{
-+ KERNEL_CALL(int, um_execve, filename, argv, envp);
-+}
-+
-+static inline long waitpid(pid_t pid, unsigned int *status, int options)
-+{
-+ KERNEL_CALL(pid_t, sys_wait4, pid, status, options, NULL)
-+}
-+
-+static inline pid_t wait(int *status)
-+{
-+ KERNEL_CALL(pid_t, sys_wait4, -1, status, 0, NULL)
-+}
-+
-+static inline pid_t setsid(void)
-+{
-+ KERNEL_CALL(pid_t, sys_setsid)
-+}
-+
-+static inline long lseek(unsigned int fd, off_t offset, unsigned int whence)
-+{
-+ KERNEL_CALL(long, sys_lseek, fd, offset, whence)
-+}
-+
-+static inline int read(unsigned int fd, char * buf, int len)
-+{
-+ KERNEL_CALL(int, sys_read, fd, buf, len)
-+}
-+
-+static inline int write(unsigned int fd, char * buf, int len)
-+{
-+ KERNEL_CALL(int, sys_write, fd, buf, len)
-+}
-+
-+#endif
-+
-+/* Save the value of __KERNEL_SYSCALLS__, undefine it, include the underlying
-+ * arch's unistd.h for the system call numbers, and restore the old
-+ * __KERNEL_SYSCALLS__.
-+ */
-+
-+#ifdef __KERNEL_SYSCALLS__
-+#define __SAVE_KERNEL_SYSCALLS__ __KERNEL_SYSCALLS__
-+#endif
-+
-+#undef __KERNEL_SYSCALLS__
-+#include "asm/arch/unistd.h"
-+
-+#ifdef __KERNEL_SYSCALLS__
-+#define __KERNEL_SYSCALLS__ __SAVE_KERNEL_SYSCALLS__
-+#endif
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/include/asm-um/user.h um/include/asm-um/user.h
---- orig/include/asm-um/user.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/user.h 2004-02-14 06:31:38.000000000 -0500
-@@ -0,0 +1,6 @@
-+#ifndef __UM_USER_H
-+#define __UM_USER_H
-+
-+#include "asm/arch/user.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/vga.h um/include/asm-um/vga.h
---- orig/include/asm-um/vga.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/vga.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_VGA_H
-+#define __UM_VGA_H
-+
-+#include "asm/arch/vga.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/asm-um/xor.h um/include/asm-um/xor.h
---- orig/include/asm-um/xor.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/asm-um/xor.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,6 @@
-+#ifndef __UM_XOR_H
-+#define __UM_XOR_H
-+
-+#include "asm-generic/xor.h"
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/linux/blk.h um/include/linux/blk.h
---- orig/include/linux/blk.h 2004-01-11 22:46:30.000000000 -0500
-+++ um/include/linux/blk.h 2004-02-14 06:29:18.000000000 -0500
-@@ -320,6 +320,24 @@
- #define DEVICE_REQUEST do_ida_request
- #define DEVICE_NR(device) (MINOR(device) >> 4)
-
-+#elif (MAJOR_NR == UBD_MAJOR)
-+
-+#define DEVICE_NAME "User-mode block device"
-+#define DEVICE_INTR do_ubd
-+#define DEVICE_REQUEST do_ubd_request
-+#define DEVICE_NR(device) (MINOR(device) >> UBD_SHIFT)
-+#define DEVICE_ON(device)
-+#define DEVICE_OFF(device)
-+
-+#elif (MAJOR_NR == COW_MAJOR)
-+
-+#define DEVICE_NAME "COW device"
-+#define DEVICE_INTR do_cow
-+#define DEVICE_REQUEST do_cow_request
-+#define DEVICE_NR(device) (MINOR(device) >> COW_SHIFT)
-+#define DEVICE_ON(device)
-+#define DEVICE_OFF(device)
-+
- #endif /* MAJOR_NR == whatever */
-
- /* provide DEVICE_xxx defaults, if not explicitly defined
-diff -Naur -X ../exclude-files orig/include/linux/fs.h um/include/linux/fs.h
---- orig/include/linux/fs.h 2003-12-16 22:16:36.000000000 -0500
-+++ um/include/linux/fs.h 2004-02-14 06:28:59.000000000 -0500
-@@ -320,6 +320,8 @@
- #include <linux/ncp_fs_i.h>
- #include <linux/proc_fs_i.h>
- #include <linux/usbdev_fs_i.h>
-+#include <linux/hostfs_fs_i.h>
-+#include <linux/hppfs_fs_i.h>
- #include <linux/jffs2_fs_i.h>
- #include <linux/cramfs_fs_sb.h>
-
-@@ -516,7 +518,9 @@
- struct proc_inode_info proc_i;
- struct socket socket_i;
- struct usbdev_inode_info usbdev_i;
-- struct jffs2_inode_info jffs2_i;
-+ struct hostfs_inode_info hostfs_i;
-+ struct hppfs_inode_info hppfs_i;
-+ struct jffs2_inode_info jffs2_i;
- void *generic_ip;
- } u;
- };
-@@ -864,6 +868,8 @@
- unsigned int (*poll) (struct file *, struct poll_table_struct *);
- int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
- int (*mmap) (struct file *, struct vm_area_struct *);
-+ void (*munmap) (struct file *, struct vm_area_struct *,
-+ unsigned long start, unsigned long len);
- int (*open) (struct inode *, struct file *);
- int (*flush) (struct file *);
- int (*release) (struct inode *, struct file *);
-diff -Naur -X ../exclude-files orig/include/linux/ghash.h um/include/linux/ghash.h
---- orig/include/linux/ghash.h 1997-07-07 11:24:28.000000000 -0400
-+++ um/include/linux/ghash.h 2003-10-21 03:26:07.000000000 -0400
-@@ -153,6 +153,26 @@
- return NULL;\
- }
-
-+/* LINKAGE - empty or "static", depending on whether you want the definitions to
-+ * be public or not
-+ * NAME - a string to stick in names to make this hash table type distinct from
-+ * any others
-+ * HASHSIZE - number of buckets
-+ * TYPE - type of data contained in the buckets - must be a structure, one
-+ * field is of type NAME_ptrs, another is the hash key
-+ * PTRS - TYPE must contain a field of type NAME_ptrs, PTRS is the name of that
-+ * field
-+ * KEYTYPE - type of the key field within TYPE
-+ * KEY - name of the key field within TYPE
-+ * KEYCMP - pointer to function that compares KEYTYPEs to each other - the
-+ * prototype is int KEYCMP(KEYTYPE, KEYTYPE), it returns zero for equal,
-+ * non-zero for not equal
-+ * HASHFN - the hash function - the prototype is int HASHFN(KEYTYPE),
-+ * it returns a number in the range 0 ... HASHSIZE - 1
-+ * Call DEF_HASH_STRUCTS, define your hash table as a NAME_table, then call
-+ * DEF_HASH.
-+ */
-+
- #define DEF_HASH_STRUCTS(NAME,HASHSIZE,TYPE) \
- \
- struct NAME##_table {\
-@@ -165,7 +185,7 @@
- TYPE * prev_hash;\
- };
-
--#define DEF_HASH(LINKAGE,NAME,HASHSIZE,TYPE,PTRS,KEYTYPE,KEY,KEYCMP,KEYEQ,HASHFN)\
-+#define DEF_HASH(LINKAGE,NAME,TYPE,PTRS,KEYTYPE,KEY,KEYCMP,HASHFN)\
- \
- LINKAGE void insert_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\
- {\
-@@ -206,12 +226,10 @@
- \
- LINKAGE TYPE * find_##NAME##_hash(struct NAME##_table * tbl, KEYTYPE pos)\
- {\
-- int ix = hashfn(pos);\
-+ int ix = HASHFN(pos);\
- TYPE * ptr = tbl->hashtable[ix];\
- while(ptr && KEYCMP(ptr->KEY, pos))\
- ptr = ptr->PTRS.next_hash;\
-- if(ptr && !KEYEQ(ptr->KEY, pos))\
-- ptr = NULL;\
- return ptr;\
- }
-
-diff -Naur -X ../exclude-files orig/include/linux/hostfs_fs_i.h um/include/linux/hostfs_fs_i.h
---- orig/include/linux/hostfs_fs_i.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/linux/hostfs_fs_i.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,21 @@
-+#ifndef _HOSTFS_FS_I
-+#define _HOSTFS_FS_I
-+
-+struct hostfs_inode_info {
-+ char *host_filename;
-+ int fd;
-+ int mode;
-+};
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/include/linux/hppfs_fs_i.h um/include/linux/hppfs_fs_i.h
---- orig/include/linux/hppfs_fs_i.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/linux/hppfs_fs_i.h 2003-10-21 03:26:07.000000000 -0400
-@@ -0,0 +1,19 @@
-+#ifndef _HPPFS_FS_I
-+#define _HPPFS_FS_I
-+
-+struct hppfs_inode_info {
-+ struct dentry *proc_dentry;
-+};
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/include/linux/kernel.h um/include/linux/kernel.h
---- orig/include/linux/kernel.h 2004-01-11 22:46:12.000000000 -0500
-+++ um/include/linux/kernel.h 2004-02-14 06:28:59.000000000 -0500
-@@ -49,7 +49,7 @@
- # define ATTRIB_NORET __attribute__((noreturn))
- # define NORET_AND noreturn,
-
--#ifdef __i386__
-+#if defined(__i386__) || defined(UM_FASTCALL)
- #define FASTCALL(x) x __attribute__((regparm(3)))
- #else
- #define FASTCALL(x) x
-diff -Naur -X ../exclude-files orig/include/linux/kernel_stat.h um/include/linux/kernel_stat.h
---- orig/include/linux/kernel_stat.h 2004-01-11 22:46:12.000000000 -0500
-+++ um/include/linux/kernel_stat.h 2004-02-14 06:28:59.000000000 -0500
-@@ -12,7 +12,7 @@
- * used by rstatd/perfmeter
- */
-
--#define DK_MAX_MAJOR 16
-+#define DK_MAX_MAJOR 99
- #define DK_MAX_DISK 16
-
- struct kernel_stat {
-diff -Naur -X ../exclude-files orig/include/linux/mm.h um/include/linux/mm.h
---- orig/include/linux/mm.h 2003-12-16 22:16:36.000000000 -0500
-+++ um/include/linux/mm.h 2004-02-14 06:28:59.000000000 -0500
-@@ -438,6 +438,18 @@
- extern struct page * FASTCALL(__alloc_pages(unsigned int gfp_mask, unsigned int order, zonelist_t *zonelist));
- extern struct page * alloc_pages_node(int nid, unsigned int gfp_mask, unsigned int order);
-
-+#ifndef HAVE_ARCH_VALIDATE
-+static inline struct page *arch_validate(struct page *page,
-+ unsigned int gfp_mask, int order)
-+{
-+ return(page);
-+}
-+#endif
-+
-+#ifndef HAVE_ARCH_FREE_PAGE
-+static inline void arch_free_page(struct page *page, int order) { }
-+#endif
-+
- static inline struct page * alloc_pages(unsigned int gfp_mask, unsigned int order)
- {
- /*
-@@ -445,7 +457,7 @@
- */
- if (order >= MAX_ORDER)
- return NULL;
-- return _alloc_pages(gfp_mask, order);
-+ return arch_validate(_alloc_pages(gfp_mask, order), gfp_mask, order);
- }
-
- #define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0)
-@@ -505,6 +517,9 @@
- int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start,
- int len, int write, int force, struct page **pages, struct vm_area_struct **vmas);
-
-+extern long do_mprotect(struct mm_struct *mm, unsigned long start,
-+ size_t len, unsigned long prot);
-+
- /*
- * On a two-level page table, this ends up being trivial. Thus the
- * inlining and the symmetry break with pte_alloc() that does all
-@@ -552,9 +567,10 @@
-
- extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
-
--extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
-- unsigned long len, unsigned long prot,
-- unsigned long flag, unsigned long pgoff);
-+extern unsigned long do_mmap_pgoff(struct mm_struct *mm, struct file *file,
-+ unsigned long addr, unsigned long len,
-+ unsigned long prot, unsigned long flag,
-+ unsigned long pgoff);
-
- static inline unsigned long do_mmap(struct file *file, unsigned long addr,
- unsigned long len, unsigned long prot,
-@@ -564,7 +580,8 @@
- if ((offset + PAGE_ALIGN(len)) < offset)
- goto out;
- if (!(offset & ~PAGE_MASK))
-- ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
-+ ret = do_mmap_pgoff(current->mm, file, addr, len, prot, flag,
-+ offset >> PAGE_SHIFT);
- out:
- return ret;
- }
-diff -Naur -X ../exclude-files orig/include/linux/proc_mm.h um/include/linux/proc_mm.h
---- orig/include/linux/proc_mm.h 1969-12-31 19:00:00.000000000 -0500
-+++ um/include/linux/proc_mm.h 2004-02-14 06:30:22.000000000 -0500
-@@ -0,0 +1,48 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __PROC_MM_H
-+#define __PROC_MM_H
-+
-+#include "linux/sched.h"
-+
-+#define MM_MMAP 54
-+#define MM_MUNMAP 55
-+#define MM_MPROTECT 56
-+#define MM_COPY_SEGMENTS 57
-+
-+struct mm_mmap {
-+ unsigned long addr;
-+ unsigned long len;
-+ unsigned long prot;
-+ unsigned long flags;
-+ unsigned long fd;
-+ unsigned long offset;
-+};
-+
-+struct mm_munmap {
-+ unsigned long addr;
-+ unsigned long len;
-+};
-+
-+struct mm_mprotect {
-+ unsigned long addr;
-+ unsigned long len;
-+ unsigned int prot;
-+};
-+
-+struct proc_mm_op {
-+ int op;
-+ union {
-+ struct mm_mmap mmap;
-+ struct mm_munmap munmap;
-+ struct mm_mprotect mprotect;
-+ int copy_segments;
-+ } u;
-+};
-+
-+extern struct mm_struct *proc_mm_get_mm(int fd);
-+
-+#endif
-diff -Naur -X ../exclude-files orig/include/linux/shmem_fs.h um/include/linux/shmem_fs.h
---- orig/include/linux/shmem_fs.h 2003-09-02 15:44:03.000000000 -0400
-+++ um/include/linux/shmem_fs.h 2003-12-09 00:03:31.000000000 -0500
-@@ -22,6 +22,8 @@
- unsigned long next_index;
- swp_entry_t i_direct[SHMEM_NR_DIRECT]; /* for the first blocks */
- void **i_indirect; /* indirect blocks */
-+ unsigned long map_direct[SHMEM_NR_DIRECT];
-+ void **map_indirect;
- unsigned long swapped; /* data pages assigned to swap */
- unsigned long flags;
- struct list_head list;
-diff -Naur -X ../exclude-files orig/include/linux/tty.h um/include/linux/tty.h
---- orig/include/linux/tty.h 2004-01-11 22:46:12.000000000 -0500
-+++ um/include/linux/tty.h 2004-02-14 06:28:59.000000000 -0500
-@@ -309,6 +309,9 @@
- spinlock_t read_lock;
- /* If the tty has a pending do_SAK, queue it here - akpm */
- struct tq_struct SAK_tq;
-+#ifdef CONFIG_TTY_LOG
-+ int log_fd;
-+#endif
- };
-
- /* tty magic number */
-@@ -365,6 +368,7 @@
- extern int specialix_init(void);
- extern int espserial_init(void);
- extern int macserial_init(void);
-+extern int stdio_init(void);
- extern int a2232board_init(void);
-
- extern int tty_paranoia_check(struct tty_struct *tty, kdev_t device,
-@@ -420,5 +424,7 @@
- extern int vt_ioctl(struct tty_struct *tty, struct file * file,
- unsigned int cmd, unsigned long arg);
-
-+extern void stdio_console_init(void);
-+
- #endif /* __KERNEL__ */
- #endif
-diff -Naur -X ../exclude-files orig/init/do_mounts.c um/init/do_mounts.c
---- orig/init/do_mounts.c 2003-12-16 22:16:36.000000000 -0500
-+++ um/init/do_mounts.c 2003-12-16 22:17:32.000000000 -0500
-@@ -154,6 +154,22 @@
- { "pf", 0x2f00 },
- { "apblock", APBLOCK_MAJOR << 8},
- { "ddv", DDV_MAJOR << 8},
-+ { "ubd0", UBD_MAJOR << 8 | 0 << 4},
-+ { "ubda", UBD_MAJOR << 8 | 0 << 4},
-+ { "ubd1", UBD_MAJOR << 8 | 1 << 4},
-+ { "ubdb", UBD_MAJOR << 8 | 1 << 4},
-+ { "ubd2", UBD_MAJOR << 8 | 2 << 4},
-+ { "ubdc", UBD_MAJOR << 8 | 2 << 4},
-+ { "ubd3", UBD_MAJOR << 8 | 3 << 4},
-+ { "ubdd", UBD_MAJOR << 8 | 3 << 4},
-+ { "ubd4", UBD_MAJOR << 8 | 4 << 4},
-+ { "ubde", UBD_MAJOR << 8 | 4 << 4},
-+ { "ubd5", UBD_MAJOR << 8 | 5 << 4},
-+ { "ubdf", UBD_MAJOR << 8 | 5 << 4},
-+ { "ubd6", UBD_MAJOR << 8 | 6 << 4},
-+ { "ubdg", UBD_MAJOR << 8 | 6 << 4},
-+ { "ubd7", UBD_MAJOR << 8 | 7 << 4},
-+ { "ubdh", UBD_MAJOR << 8 | 7 << 4},
- { "jsfd", JSFD_MAJOR << 8},
- #if defined(CONFIG_ARCH_S390)
- { "dasda", (DASD_MAJOR << MINORBITS) },
-diff -Naur -X ../exclude-files orig/kernel/panic.c um/kernel/panic.c
---- orig/kernel/panic.c 2003-12-16 22:16:36.000000000 -0500
-+++ um/kernel/panic.c 2003-12-16 22:17:32.000000000 -0500
-@@ -74,7 +74,7 @@
- smp_send_stop();
- #endif
-
-- notifier_call_chain(&panic_notifier_list, 0, NULL);
-+ notifier_call_chain(&panic_notifier_list, 0, buf);
-
- if (panic_timeout > 0)
- {
-diff -Naur -X ../exclude-files orig/MAINTAINERS um/MAINTAINERS
---- orig/MAINTAINERS 2003-12-16 22:16:23.000000000 -0500
-+++ um/MAINTAINERS 2003-12-16 22:17:22.000000000 -0500
-@@ -2055,6 +2055,14 @@
- L: linux-usb-devel@lists.sourceforge.net
- W: http://usb.in.tum.de
- S: Maintained
-+
-+USER-MODE PORT
-+P: Jeff Dike
-+M: jdike@karaya.com
-+L: user-mode-linux-devel@lists.sourceforge.net
-+L: user-mode-linux-user@lists.sourceforge.net
-+W: http://user-mode-linux.sourceforge.net
-+S: Maintained
-
- USB "USBNET" DRIVER
- P: David Brownell
-diff -Naur -X ../exclude-files orig/Makefile um/Makefile
---- orig/Makefile 2004-02-14 06:26:12.000000000 -0500
-+++ um/Makefile 2004-02-14 06:26:19.000000000 -0500
-@@ -5,7 +5,15 @@
-
- KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
-
--ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
-+# SUBARCH tells the usermode build what the underlying arch is. That is set
-+# first, and if a usermode build is happening, the "ARCH=um" on the command
-+# line overrides the setting of ARCH below. If a native build is happening,
-+# then ARCH is assigned, getting whatever value it gets normally, and
-+# SUBARCH is subsequently ignored.
-+
-+SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
-+ARCH := $(SUBARCH)
-+
- KERNELPATH=kernel-$(shell echo $(KERNELRELEASE) | sed -e "s/-//g")
-
- CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
-diff -Naur -X ../exclude-files orig/mm/Makefile um/mm/Makefile
---- orig/mm/Makefile 2002-08-21 11:47:43.000000000 -0400
-+++ um/mm/Makefile 2003-10-21 03:26:08.000000000 -0400
-@@ -17,5 +17,6 @@
- shmem.o
-
- obj-$(CONFIG_HIGHMEM) += highmem.o
-+obj-$(CONFIG_PROC_MM) += proc_mm.o
-
- include $(TOPDIR)/Rules.make
-diff -Naur -X ../exclude-files orig/mm/mmap.c um/mm/mmap.c
---- orig/mm/mmap.c 2003-12-16 22:16:36.000000000 -0500
-+++ um/mm/mmap.c 2003-12-16 22:17:32.000000000 -0500
-@@ -390,10 +390,11 @@
- return 0;
- }
-
--unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, unsigned long len,
-- unsigned long prot, unsigned long flags, unsigned long pgoff)
-+unsigned long do_mmap_pgoff(struct mm_struct *mm, struct file * file,
-+ unsigned long addr, unsigned long len,
-+ unsigned long prot, unsigned long flags,
-+ unsigned long pgoff)
- {
-- struct mm_struct * mm = current->mm;
- struct vm_area_struct * vma, * prev;
- unsigned int vm_flags;
- int correct_wcount = 0;
-@@ -994,6 +995,11 @@
- remove_shared_vm_struct(mpnt);
- mm->map_count--;
-
-+ if((mpnt->vm_file != NULL) && (mpnt->vm_file->f_op != NULL) &&
-+ (mpnt->vm_file->f_op->munmap != NULL))
-+ mpnt->vm_file->f_op->munmap(mpnt->vm_file, mpnt, st,
-+ size);
-+
- zap_page_range(mm, st, size);
-
- /*
-diff -Naur -X ../exclude-files orig/mm/mprotect.c um/mm/mprotect.c
---- orig/mm/mprotect.c 2003-12-16 22:16:36.000000000 -0500
-+++ um/mm/mprotect.c 2003-12-16 22:17:32.000000000 -0500
-@@ -264,7 +264,8 @@
- return 0;
- }
-
--asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot)
-+long do_mprotect(struct mm_struct *mm, unsigned long start, size_t len,
-+ unsigned long prot)
- {
- unsigned long nstart, end, tmp;
- struct vm_area_struct * vma, * next, * prev;
-@@ -281,9 +282,9 @@
- if (end == start)
- return 0;
-
-- down_write(¤t->mm->mmap_sem);
-+ down_write(&mm->mmap_sem);
-
-- vma = find_vma_prev(current->mm, start, &prev);
-+ vma = find_vma_prev(mm, start, &prev);
- error = -ENOMEM;
- if (!vma || vma->vm_start > start)
- goto out;
-@@ -332,6 +333,11 @@
- prev->vm_mm->map_count--;
- }
- out:
-- up_write(¤t->mm->mmap_sem);
-+ up_write(&mm->mmap_sem);
- return error;
- }
-+
-+asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot)
-+{
-+ return(do_mprotect(current->mm, start, len, prot));
-+}
-diff -Naur -X ../exclude-files orig/mm/page_alloc.c um/mm/page_alloc.c
---- orig/mm/page_alloc.c 2003-12-16 22:16:36.000000000 -0500
-+++ um/mm/page_alloc.c 2003-12-16 22:17:32.000000000 -0500
-@@ -89,6 +89,7 @@
- struct page *base;
- zone_t *zone;
-
-+ arch_free_page(page, order);
- /*
- * Yes, think what happens when other parts of the kernel take
- * a reference to a page in order to pin it for io. -ben
-diff -Naur -X ../exclude-files orig/mm/proc_mm.c um/mm/proc_mm.c
---- orig/mm/proc_mm.c 1969-12-31 19:00:00.000000000 -0500
-+++ um/mm/proc_mm.c 2003-10-21 03:26:08.000000000 -0400
-@@ -0,0 +1,173 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/init.h"
-+#include "linux/proc_fs.h"
-+#include "linux/proc_mm.h"
-+#include "linux/file.h"
-+#include "asm/uaccess.h"
-+#include "asm/mmu_context.h"
-+
-+static struct file_operations proc_mm_fops;
-+
-+struct mm_struct *proc_mm_get_mm(int fd)
-+{
-+ struct mm_struct *ret = ERR_PTR(-EBADF);
-+ struct file *file;
-+
-+ file = fget(fd);
-+ if (!file)
-+ goto out;
-+
-+ ret = ERR_PTR(-EINVAL);
-+ if(file->f_op != &proc_mm_fops)
-+ goto out_fput;
-+
-+ ret = file->private_data;
-+ out_fput:
-+ fput(file);
-+ out:
-+ return(ret);
-+}
-+
-+extern long do_mmap2(struct mm_struct *mm, unsigned long addr,
-+ unsigned long len, unsigned long prot,
-+ unsigned long flags, unsigned long fd,
-+ unsigned long pgoff);
-+
-+static ssize_t write_proc_mm(struct file *file, const char *buffer,
-+ size_t count, loff_t *ppos)
-+{
-+ struct mm_struct *mm = file->private_data;
-+ struct proc_mm_op req;
-+ int n, ret;
-+
-+ if(count > sizeof(req))
-+ return(-EINVAL);
-+
-+ n = copy_from_user(&req, buffer, count);
-+ if(n != 0)
-+ return(-EFAULT);
-+
-+ ret = count;
-+ switch(req.op){
-+ case MM_MMAP: {
-+ struct mm_mmap *map = &req.u.mmap;
-+
-+ ret = do_mmap2(mm, map->addr, map->len, map->prot,
-+ map->flags, map->fd, map->offset >> PAGE_SHIFT);
-+ if((ret & ~PAGE_MASK) == 0)
-+ ret = count;
-+
-+ break;
-+ }
-+ case MM_MUNMAP: {
-+ struct mm_munmap *unmap = &req.u.munmap;
-+
-+ down_write(&mm->mmap_sem);
-+ ret = do_munmap(mm, unmap->addr, unmap->len);
-+ up_write(&mm->mmap_sem);
-+
-+ if(ret == 0)
-+ ret = count;
-+ break;
-+ }
-+ case MM_MPROTECT: {
-+ struct mm_mprotect *protect = &req.u.mprotect;
-+
-+ ret = do_mprotect(mm, protect->addr, protect->len,
-+ protect->prot);
-+ if(ret == 0)
-+ ret = count;
-+ break;
-+ }
-+
-+ case MM_COPY_SEGMENTS: {
-+ struct mm_struct *from = proc_mm_get_mm(req.u.copy_segments);
-+
-+ if(IS_ERR(from)){
-+ ret = PTR_ERR(from);
-+ break;
-+ }
-+
-+ mm_copy_segments(from, mm);
-+ break;
-+ }
-+ default:
-+ ret = -EINVAL;
-+ break;
-+ }
-+
-+ return(ret);
-+}
-+
-+static int open_proc_mm(struct inode *inode, struct file *file)
-+{
-+ struct mm_struct *mm = mm_alloc();
-+ int ret;
-+
-+ ret = -ENOMEM;
-+ if(mm == NULL)
-+ goto out_mem;
-+
-+ ret = init_new_context(current, mm);
-+ if(ret)
-+ goto out_free;
-+
-+ spin_lock(&mmlist_lock);
-+ list_add(&mm->mmlist, ¤t->mm->mmlist);
-+ mmlist_nr++;
-+ spin_unlock(&mmlist_lock);
-+
-+ file->private_data = mm;
-+
-+ return(0);
-+
-+ out_free:
-+ mmput(mm);
-+ out_mem:
-+ return(ret);
-+}
-+
-+static int release_proc_mm(struct inode *inode, struct file *file)
-+{
-+ struct mm_struct *mm = file->private_data;
-+
-+ mmput(mm);
-+ return(0);
-+}
-+
-+static struct file_operations proc_mm_fops = {
-+ .open = open_proc_mm,
-+ .release = release_proc_mm,
-+ .write = write_proc_mm,
-+};
-+
-+static int make_proc_mm(void)
-+{
-+ struct proc_dir_entry *ent;
-+
-+ ent = create_proc_entry("mm", 0222, &proc_root);
-+ if(ent == NULL){
-+ printk("make_proc_mm : Failed to register /proc/mm\n");
-+ return(0);
-+ }
-+ ent->proc_fops = &proc_mm_fops;
-+
-+ return(0);
-+}
-+
-+__initcall(make_proc_mm);
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only. This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-diff -Naur -X ../exclude-files orig/mm/shmem.c um/mm/shmem.c
---- orig/mm/shmem.c 2003-12-16 22:16:36.000000000 -0500
-+++ um/mm/shmem.c 2003-12-16 22:17:32.000000000 -0500
-@@ -128,16 +128,17 @@
- * +-> 48-51
- * +-> 52-55
- */
--static swp_entry_t *shmem_swp_entry(struct shmem_inode_info *info, unsigned long index, unsigned long *page)
-+static void *shmem_block(unsigned long index, unsigned long *page,
-+ unsigned long *direct, void ***indirect)
- {
- unsigned long offset;
- void **dir;
-
- if (index < SHMEM_NR_DIRECT)
-- return info->i_direct+index;
-- if (!info->i_indirect) {
-+ return direct+index;
-+ if (!*indirect) {
- if (page) {
-- info->i_indirect = (void **) *page;
-+ *indirect = (void **) *page;
- *page = 0;
- }
- return NULL; /* need another page */
-@@ -146,7 +147,7 @@
- index -= SHMEM_NR_DIRECT;
- offset = index % ENTRIES_PER_PAGE;
- index /= ENTRIES_PER_PAGE;
-- dir = info->i_indirect;
-+ dir = *indirect;
-
- if (index >= ENTRIES_PER_PAGE/2) {
- index -= ENTRIES_PER_PAGE/2;
-@@ -169,7 +170,21 @@
- *dir = (void *) *page;
- *page = 0;
- }
-- return (swp_entry_t *) *dir + offset;
-+ return (unsigned long **) *dir + offset;
-+}
-+
-+static swp_entry_t *shmem_swp_entry(struct shmem_inode_info *info, unsigned long index, unsigned long *page)
-+{
-+ return((swp_entry_t *) shmem_block(index, page,
-+ (unsigned long *) info->i_direct,
-+ &info->i_indirect));
-+}
-+
-+static unsigned long *shmem_map_count(struct shmem_inode_info *info,
-+ unsigned long index, unsigned long *page)
-+{
-+ return((unsigned long *) shmem_block(index, page, info->map_direct,
-+ &info->map_indirect));
- }
-
- /*
-@@ -838,6 +853,7 @@
- ops = &shmem_vm_ops;
- if (!S_ISREG(inode->i_mode))
- return -EACCES;
-+
- UPDATE_ATIME(inode);
- vma->vm_ops = ops;
- return 0;
-@@ -1723,4 +1739,125 @@
- return 0;
- }
-
-+static int adjust_map_counts(struct shmem_inode_info *info,
-+ unsigned long offset, unsigned long len,
-+ int adjust)
-+{
-+ unsigned long idx, i, *count, page = 0;
-+
-+ spin_lock(&info->lock);
-+ offset >>= PAGE_SHIFT;
-+ len >>= PAGE_SHIFT;
-+ for(i = 0; i < len; i++){
-+ idx = (i + offset) >> (PAGE_CACHE_SHIFT - PAGE_SHIFT);
-+
-+ while((count = shmem_map_count(info, idx, &page)) == NULL){
-+ spin_unlock(&info->lock);
-+ page = get_zeroed_page(GFP_KERNEL);
-+ if(page == 0)
-+ return(-ENOMEM);
-+ spin_lock(&info->lock);
-+ }
-+
-+ if(page != 0)
-+ free_page(page);
-+
-+ *count += adjust;
-+ }
-+ spin_unlock(&info->lock);
-+ return(0);
-+}
-+
- EXPORT_SYMBOL(shmem_file_setup);
-+
-+struct file_operations anon_file_operations;
-+
-+static int anon_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+ struct file *new;
-+ struct inode *inode;
-+ loff_t size = vma->vm_end - vma->vm_start;
-+ int err;
-+
-+ if(file->private_data == NULL){
-+ new = shmem_file_setup("dev/anon", size);
-+ if(IS_ERR(new))
-+ return(PTR_ERR(new));
-+
-+ new->f_op = &anon_file_operations;
-+ file->private_data = new;
-+ }
-+
-+ if (vma->vm_file)
-+ fput(vma->vm_file);
-+ vma->vm_file = file->private_data;
-+ get_file(vma->vm_file);
-+
-+ inode = vma->vm_file->f_dentry->d_inode;
-+ err = adjust_map_counts(SHMEM_I(inode), vma->vm_pgoff, size, 1);
-+ if(err)
-+ return(err);
-+
-+ vma->vm_ops = &shmem_vm_ops;
-+ return 0;
-+}
-+
-+static void anon_munmap(struct file *file, struct vm_area_struct *vma,
-+ unsigned long start, unsigned long len)
-+{
-+ struct inode *inode = file->f_dentry->d_inode;
-+ struct shmem_inode_info *info = SHMEM_I(inode);
-+ pgd_t *pgd;
-+ pmd_t *pmd;
-+ pte_t *pte;
-+ struct page *page;
-+ unsigned long addr, idx, *count;
-+
-+ for(addr = start; addr < start + len; addr += PAGE_SIZE){
-+ idx = (addr - vma->vm_start + vma->vm_pgoff);
-+ idx >>= PAGE_CACHE_SHIFT;
-+
-+ count = shmem_map_count(info, idx, NULL);
-+ BUG_ON(count == NULL);
-+
-+ (*count)--;
-+ if(*count > 0)
-+ continue;
-+
-+ pgd = pgd_offset(vma->vm_mm, addr);
-+ if(pgd_none(*pgd))
-+ continue;
-+
-+ pmd = pmd_offset(pgd, addr);
-+ if(pmd_none(*pmd))
-+ continue;
-+
-+ pte = pte_offset(pmd, addr);
-+ if(!pte_present(*pte)) /* XXX need to handle swapped pages */
-+ continue;
-+
-+ *pte = pte_mkclean(*pte);
-+
-+ page = pte_page(*pte);
-+ LockPage(page);
-+ lru_cache_del(page);
-+ ClearPageDirty(page);
-+ remove_inode_page(page);
-+ UnlockPage(page);
-+
-+ page_cache_release(page);
-+ }
-+}
-+
-+int anon_release(struct inode *inode, struct file *file)
-+{
-+ if(file->private_data != NULL)
-+ fput(file->private_data);
-+ return(0);
-+}
-+
-+struct file_operations anon_file_operations = {
-+ .mmap = anon_mmap,
-+ .munmap = anon_munmap,
-+ .release = anon_release,
-+};
+++ /dev/null
- fs/inode.c | 1
- fs/namei.c | 66 ++++++++++++++++++++++++++++++++++++++---------------
- include/linux/fs.h | 11 ++++----
- 3 files changed, 54 insertions(+), 24 deletions(-)
-
-Index: linux-2.4.24/fs/namei.c
-===================================================================
---- linux-2.4.24.orig/fs/namei.c 2004-06-24 09:08:27.000000000 +0400
-+++ linux-2.4.24/fs/namei.c 2004-06-27 21:32:00.000000000 +0400
-@@ -103,6 +103,38 @@
- }
- EXPORT_SYMBOL(intent_release);
-
-+void *lock_dir(struct inode *dir, struct qstr *name)
-+{
-+ unsigned long hash;
-+
-+ if (!IS_PDIROPS(dir)) {
-+ down(&dir->i_sem);
-+ return 0;
-+ }
-+
-+ /* OK. fs understands parallel directory operations.
-+ * so, we try to acquire lock for hash of requested
-+ * filename in order to prevent any operations with
-+ * same name in same time -bzzz */
-+
-+ /* calculate name hash */
-+ hash = full_name_hash(name->name, name->len);
-+
-+ /* lock this hash */
-+ return dynlock_lock(&dir->i_dcache_lock, hash, 1, GFP_ATOMIC);
-+}
-+EXPORT_SYMBOL(lock_dir);
-+
-+void unlock_dir(struct inode *dir, void *lock)
-+{
-+ if (!IS_PDIROPS(dir)) {
-+ up(&dir->i_sem);
-+ return;
-+ }
-+ dynlock_unlock(&dir->i_dcache_lock, lock);
-+}
-+EXPORT_SYMBOL(unlock_dir);
-+
- /* In order to reduce some races, while at the same time doing additional
- * checking and hopefully speeding things up, we copy filenames to the
- * kernel data space before using them..
-@@ -307,10 +339,11 @@
- struct dentry * result;
- struct inode *dir = parent->d_inode;
- int counter = 0;
-+ void *lock;
-
- again:
- counter++;
-- down(&dir->i_sem);
-+ lock = lock_dir(dir, name);
- /*
- * First re-do the cached lookup just in case it was created
- * while we waited for the directory semaphore..
-@@ -334,7 +367,7 @@
- else
- result = dentry;
- }
-- up(&dir->i_sem);
-+ unlock_dir(dir, lock);
- return result;
- }
-
-@@ -342,7 +375,7 @@
- * Uhhuh! Nasty case: the cache was re-populated while
- * we waited on the semaphore. Need to revalidate.
- */
-- up(&dir->i_sem);
-+ unlock_dir(dir, lock);
- if (result->d_op && result->d_op->d_revalidate) {
- if (!result->d_op->d_revalidate(result, flags) && !d_invalidate(result)) {
- dput(result);
-@@ -1174,13 +1207,13 @@
- goto exit;
-
- dir = nd->dentry;
-- down(&dir->d_inode->i_sem);
-+ nd->lock = lock_dir(dir->d_inode, &nd->last);
- dentry = lookup_hash_it(&nd->last, nd->dentry, nd, it);
-
- do_last:
- error = PTR_ERR(dentry);
- if (IS_ERR(dentry)) {
-- up(&dir->d_inode->i_sem);
-+ unlock_dir(dir->d_inode, nd->lock);
- goto exit;
- }
-
-@@ -1189,7 +1222,7 @@
- if (!dentry->d_inode) {
- error = vfs_create_it(dir->d_inode, dentry,
- mode & ~current->fs->umask, it);
-- up(&dir->d_inode->i_sem);
-+ unlock_dir(dir->d_inode, nd->lock);
- dput(nd->dentry);
- nd->dentry = dentry;
- if (error)
-@@ -1203,7 +1236,7 @@
- /*
- * It already exists.
- */
-- up(&dir->d_inode->i_sem);
-+ unlock_dir(dir->d_inode, nd->lock);
-
- error = -EEXIST;
- if (flag & O_EXCL)
-@@ -1350,7 +1383,7 @@
- goto exit;
- }
- dir = nd->dentry;
-- down(&dir->d_inode->i_sem);
-+ nd->lock = lock_dir(dir->d_inode, &nd->last);
- dentry = lookup_hash_it(&nd->last, nd->dentry, nd, it);
- putname(nd->last.name);
- goto do_last;
-@@ -1368,7 +1401,7 @@
- {
- struct dentry *dentry;
-
-- down(&nd->dentry->d_inode->i_sem);
-+ nd->lock = lock_dir(nd->dentry->d_inode, &nd->last);
- dentry = ERR_PTR(-EEXIST);
- if (nd->last_type != LAST_NORM)
- goto fail;
-@@ -1461,7 +1494,7 @@
- }
- dput(dentry);
- }
-- up(&nd.dentry->d_inode->i_sem);
-+ unlock_dir(nd.dentry->d_inode, nd.lock);
- out2:
- path_release(&nd);
- out:
-@@ -1528,7 +1561,7 @@
- mode & ~current->fs->umask);
- dput(dentry);
- }
-- up(&nd.dentry->d_inode->i_sem);
-+ unlock_dir(nd.dentry->d_inode, nd.lock);
- out2:
- path_release(&nd);
- out:
-@@ -1638,14 +1671,14 @@
- if (error != -EOPNOTSUPP)
- goto exit1;
- }
-- down(&nd.dentry->d_inode->i_sem);
-+ nd.lock = lock_dir(nd.dentry->d_inode, &nd.last);
- dentry = lookup_hash_it(&nd.last, nd.dentry, &nd, NULL);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_rmdir(nd.dentry->d_inode, dentry);
- dput(dentry);
- }
-- up(&nd.dentry->d_inode->i_sem);
-+ unlock_dir(nd.dentry->d_inode, nd.lock);
- exit1:
- path_release(&nd);
- exit:
-@@ -1704,7 +1737,7 @@
- if (error != -EOPNOTSUPP)
- goto exit1;
- }
-- down(&nd.dentry->d_inode->i_sem);
-+ nd.lock = lock_dir(nd.dentry->d_inode, &nd.last);
- dentry = lookup_hash_it(&nd.last, nd.dentry, &nd, NULL);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
-@@ -1715,7 +1748,7 @@
- exit2:
- dput(dentry);
- }
-- up(&nd.dentry->d_inode->i_sem);
-+ unlock_dir(nd.dentry->d_inode, nd.lock);
- exit1:
- path_release(&nd);
- exit:
-@@ -1789,7 +1822,7 @@
- error = vfs_symlink(nd.dentry->d_inode, dentry, from);
- dput(dentry);
- }
-- up(&nd.dentry->d_inode->i_sem);
-+ unlock_dir(nd.dentry->d_inode, nd.lock);
- out2:
- path_release(&nd);
- out:
-@@ -1885,7 +1918,7 @@
- error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
- dput(new_dentry);
- }
-- up(&nd.dentry->d_inode->i_sem);
-+ unlock_dir(nd.dentry->d_inode, nd.lock);
- out_release:
- path_release(&nd);
- out:
-Index: linux-2.4.24/fs/inode.c
-===================================================================
---- linux-2.4.24.orig/fs/inode.c 2004-06-24 09:08:27.000000000 +0400
-+++ linux-2.4.24/fs/inode.c 2004-06-24 09:08:29.000000000 +0400
-@@ -119,6 +119,7 @@
- mapping->host = inode;
- mapping->gfp_mask = GFP_HIGHUSER;
- inode->i_mapping = mapping;
-+ dynlock_init(&inode->i_dcache_lock);
- }
- return inode;
- }
-Index: linux-2.4.24/include/linux/fs.h
-===================================================================
---- linux-2.4.24.orig/include/linux/fs.h 2004-06-24 09:08:29.000000000 +0400
-+++ linux-2.4.24/include/linux/fs.h 2004-06-24 09:08:29.000000000 +0400
-@@ -21,6 +21,7 @@
- #include <linux/cache.h>
- #include <linux/stddef.h>
- #include <linux/string.h>
-+#include <linux/dynlocks.h>
-
- #include <asm/atomic.h>
- #include <asm/bitops.h>
-@@ -139,6 +140,7 @@
- #define S_IMMUTABLE 16 /* Immutable file */
- #define S_DEAD 32 /* removed, but still open directory */
- #define S_NOQUOTA 64 /* Inode is not counted to quota */
-+#define S_PDIROPS 256 /* Parallel directory operations */
-
- /*
- * Note that nosuid etc flags are inode-specific: setting some file-system
-@@ -165,6 +167,7 @@
- #define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE)
- #define IS_NOATIME(inode) (__IS_FLG(inode, MS_NOATIME) || ((inode)->i_flags & S_NOATIME))
- #define IS_NODIRATIME(inode) __IS_FLG(inode, MS_NODIRATIME)
-+#define IS_PDIROPS(inode) __IS_FLG(inode, S_PDIROPS)
-
- #define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD)
-
-@@ -500,6 +503,7 @@
- atomic_t i_writecount;
- unsigned int i_attr_flags;
- __u32 i_generation;
-+ struct dynlock i_dcache_lock; /* for parallel directory ops */
- union {
- struct minix_inode_info minix_i;
- struct ext2_inode_info ext2_i;
-@@ -714,6 +718,7 @@
- unsigned int flags;
- int last_type;
- struct lookup_intent *intent;
-+ void *lock;
- };
-
- /*
-@@ -1629,12 +1634,6 @@
- return dget(dentry->d_parent);
- }
-
--static inline void unlock_dir(struct dentry *dir)
--{
-- up(&dir->d_inode->i_sem);
-- dput(dir);
--}
--
- /*
- * Whee.. Deadlock country. Happily there are only two VFS
- * operations that does this..
+++ /dev/null
- fs/dcache.c | 19 ++
- fs/exec.c | 17 +-
- fs/namei.c | 295 +++++++++++++++++++++++++++++++++++++++-------
- fs/namespace.c | 28 +++-
- fs/open.c | 172 +++++++++++++++++++-------
- fs/stat.c | 52 +++++---
- include/linux/dcache.h | 60 +++++++++
- include/linux/fs.h | 32 ++++
- include/linux/fs_struct.h | 4
- kernel/exit.c | 3
- kernel/fork.c | 3
- kernel/ksyms.c | 1
- 12 files changed, 558 insertions(+), 128 deletions(-)
-
-Index: lum/fs/dcache.c
-===================================================================
---- lum.orig/fs/dcache.c 2003-06-13 10:51:37.000000000 -0400
-+++ lum/fs/dcache.c 2004-06-07 17:19:43.000000000 -0400
-@@ -181,6 +181,13 @@
- spin_unlock(&dcache_lock);
- return 0;
- }
-+
-+ /* network invalidation by Lustre */
-+ if (dentry->d_flags & DCACHE_LUSTRE_INVALID) {
-+ spin_unlock(&dcache_lock);
-+ return 0;
-+ }
-+
- /*
- * Check whether to do a partial shrink_dcache
- * to get rid of unused child entries.
-@@ -830,13 +837,19 @@
- * Adds a dentry to the hash according to its name.
- */
-
--void d_rehash(struct dentry * entry)
-+void __d_rehash(struct dentry * entry, int lock)
- {
- struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash);
- if (!list_empty(&entry->d_hash)) BUG();
-- spin_lock(&dcache_lock);
-+ if (lock) spin_lock(&dcache_lock);
- list_add(&entry->d_hash, list);
-- spin_unlock(&dcache_lock);
-+ if (lock) spin_unlock(&dcache_lock);
-+}
-+EXPORT_SYMBOL(__d_rehash);
-+
-+void d_rehash(struct dentry * entry)
-+{
-+ __d_rehash(entry, 1);
- }
-
- #define do_switch(x,y) do { \
-Index: lum/fs/exec.c
-===================================================================
---- lum.orig/fs/exec.c 2003-11-28 13:26:21.000000000 -0500
-+++ lum/fs/exec.c 2004-06-07 17:19:43.000000000 -0400
-@@ -112,8 +112,10 @@
- struct file * file;
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_OPEN,
-+ .it_flags = FMODE_READ|FMODE_EXEC };
-
-- error = user_path_walk(library, &nd);
-+ error = user_path_walk_it(library, &nd, &it);
- if (error)
- goto out;
-
-@@ -125,7 +127,8 @@
- if (error)
- goto exit;
-
-- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
-+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it);
-+ intent_release(&it);
- error = PTR_ERR(file);
- if (IS_ERR(file))
- goto out;
-@@ -374,8 +377,10 @@
- struct inode *inode;
- struct file *file;
- int err = 0;
-+ struct lookup_intent it = { .it_op = IT_OPEN,
-+ .it_flags = FMODE_READ|FMODE_EXEC };
-
-- err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd);
-+ err = path_lookup_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it);
- file = ERR_PTR(err);
- if (!err) {
- inode = nd.dentry->d_inode;
-@@ -387,7 +392,8 @@
- err = -EACCES;
- file = ERR_PTR(err);
- if (!err) {
-- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
-+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it);
-+ intent_release(&it);
- if (!IS_ERR(file)) {
- err = deny_write_access(file);
- if (err) {
-@@ -399,6 +405,7 @@
- return file;
- }
- }
-+ intent_release(&it);
- path_release(&nd);
- }
- goto out;
-@@ -1132,7 +1139,7 @@
- goto close_fail;
- if (!file->f_op->write)
- goto close_fail;
-- if (do_truncate(file->f_dentry, 0) != 0)
-+ if (do_truncate(file->f_dentry, 0, 0) != 0)
- goto close_fail;
-
- retval = binfmt->core_dump(signr, regs, file);
-Index: lum/fs/namei.c
-===================================================================
---- lum.orig/fs/namei.c 2003-08-25 07:44:43.000000000 -0400
-+++ lum/fs/namei.c 2004-06-07 17:24:47.000000000 -0400
-@@ -94,6 +94,13 @@
- * XEmacs seems to be relying on it...
- */
-
-+void intent_release(struct lookup_intent *it)
-+{
-+ if (it && it->it_op_release)
-+ it->it_op_release(it);
-+
-+}
-+
- /* In order to reduce some races, while at the same time doing additional
- * checking and hopefully speeding things up, we copy filenames to the
- * kernel data space before using them..
-@@ -260,10 +267,20 @@
- * Internal lookup() using the new generic dcache.
- * SMP-safe
- */
--static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
-+static struct dentry *cached_lookup(struct dentry *parent, struct qstr *name,
-+ int flags, struct nameidata *nd,
-+ struct lookup_intent *it)
- {
- struct dentry * dentry = d_lookup(parent, name);
-
-+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) {
-+ if (!dentry->d_op->d_revalidate_it(dentry, flags, nd, it) &&
-+ !d_invalidate(dentry)) {
-+ dput(dentry);
-+ dentry = NULL;
-+ }
-+ return dentry;
-+ } else
- if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
- dput(dentry);
-@@ -281,11 +298,16 @@
- * make sure that nobody added the entry to the dcache in the meantime..
- * SMP-safe
- */
--static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)
-+static struct dentry *real_lookup(struct dentry *parent, struct qstr *name,
-+ int flags, struct nameidata *nd,
-+ struct lookup_intent *it)
- {
- struct dentry * result;
- struct inode *dir = parent->d_inode;
-+ int counter = 0;
-
-+again:
-+ counter++;
- down(&dir->i_sem);
- /*
- * First re-do the cached lookup just in case it was created
-@@ -300,6 +322,9 @@
- result = ERR_PTR(-ENOMEM);
- if (dentry) {
- lock_kernel();
-+ if (dir->i_op->lookup_it)
-+ result = dir->i_op->lookup_it(dir, dentry, nd, it, flags);
-+ else
- result = dir->i_op->lookup(dir, dentry);
- unlock_kernel();
- if (result)
-@@ -321,6 +346,15 @@
- dput(result);
- result = ERR_PTR(-ENOENT);
- }
-+ } else if (result->d_op && result->d_op->d_revalidate_it) {
-+ if (!result->d_op->d_revalidate_it(result, flags, nd, it) &&
-+ !d_invalidate(result)) {
-+ dput(result);
-+ if (counter > 10)
-+ result = ERR_PTR(-ESTALE);
-+ if (!IS_ERR(result))
-+ goto again;
-+ }
- }
- return result;
- }
-@@ -332,7 +366,8 @@
- * Without that kind of total limit, nasty chains of consecutive
- * symlinks can cause almost arbitrarily long lookups.
- */
--static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
-+static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd,
-+ struct lookup_intent *it)
- {
- int err;
- if (current->link_count >= 5)
-@@ -346,10 +381,12 @@
- current->link_count++;
- current->total_link_count++;
- UPDATE_ATIME(dentry->d_inode);
-+ nd->intent = it;
- err = dentry->d_inode->i_op->follow_link(dentry, nd);
- current->link_count--;
- return err;
- loop:
-+ intent_release(it);
- path_release(nd);
- return -ELOOP;
- }
-@@ -447,7 +484,8 @@
- *
- * We expect 'base' to be positive and a directory.
- */
--int link_path_walk(const char * name, struct nameidata *nd)
-+int link_path_walk_it(const char *name, struct nameidata *nd,
-+ struct lookup_intent *it)
- {
- struct dentry *dentry;
- struct inode *inode;
-@@ -520,9 +558,9 @@
- break;
- }
- /* This does the actual lookups.. */
-- dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
-+ dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, nd, NULL);
- if (!dentry) {
-- dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
-+ dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, nd, NULL);
- err = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- break;
-@@ -540,7 +578,7 @@
- goto out_dput;
-
- if (inode->i_op->follow_link) {
-- err = do_follow_link(dentry, nd);
-+ err = do_follow_link(dentry, nd, NULL);
- dput(dentry);
- if (err)
- goto return_err;
-@@ -556,7 +594,7 @@
- nd->dentry = dentry;
- }
- err = -ENOTDIR;
-- if (!inode->i_op->lookup)
-+ if (!inode->i_op->lookup && !inode->i_op->lookup_it)
- break;
- continue;
- /* here ends the main loop */
-@@ -583,9 +621,9 @@
- if (err < 0)
- break;
- }
-- dentry = cached_lookup(nd->dentry, &this, 0);
-+ dentry = cached_lookup(nd->dentry, &this, 0, nd, it);
- if (!dentry) {
-- dentry = real_lookup(nd->dentry, &this, 0);
-+ dentry = real_lookup(nd->dentry, &this, 0, nd, it);
- err = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- break;
-@@ -595,7 +633,7 @@
- inode = dentry->d_inode;
- if ((lookup_flags & LOOKUP_FOLLOW)
- && inode && inode->i_op && inode->i_op->follow_link) {
-- err = do_follow_link(dentry, nd);
-+ err = do_follow_link(dentry, nd, it);
- dput(dentry);
- if (err)
- goto return_err;
-@@ -609,7 +647,8 @@
- goto no_inode;
- if (lookup_flags & LOOKUP_DIRECTORY) {
- err = -ENOTDIR;
-- if (!inode->i_op || !inode->i_op->lookup)
-+ if (!inode->i_op ||
-+ (!inode->i_op->lookup && !inode->i_op->lookup_it))
- break;
- }
- goto return_base;
-@@ -635,6 +674,27 @@
- * Check the cached dentry for staleness.
- */
- dentry = nd->dentry;
-+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) {
-+ err = -ESTALE;
-+ if (!dentry->d_op->d_revalidate_it(dentry, 0, nd, it)) {
-+ struct dentry *new;
-+ err = permission(dentry->d_parent->d_inode,
-+ MAY_EXEC);
-+ if (err)
-+ break;
-+ new = real_lookup(dentry->d_parent,
-+ &dentry->d_name, 0, nd, it);
-+ if (IS_ERR(new)) {
-+ err = PTR_ERR(new);
-+ break;
-+ }
-+ d_invalidate(dentry);
-+ dput(dentry);
-+ nd->dentry = new;
-+ }
-+ if (!nd->dentry->d_inode)
-+ goto no_inode;
-+ } else
- if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- err = -ESTALE;
- if (!dentry->d_op->d_revalidate(dentry, 0)) {
-@@ -648,15 +708,28 @@
- dput(dentry);
- break;
- }
-+ if (err)
-+ intent_release(it);
- path_release(nd);
- return_err:
- return err;
- }
-
-+int link_path_walk(const char * name, struct nameidata *nd)
-+{
-+ return link_path_walk_it(name, nd, NULL);
-+}
-+
-+int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it)
-+{
-+ current->total_link_count = 0;
-+ return link_path_walk_it(name, nd, it);
-+}
-+
- int path_walk(const char * name, struct nameidata *nd)
- {
- current->total_link_count = 0;
-- return link_path_walk(name, nd);
-+ return link_path_walk_it(name, nd, NULL);
- }
-
- /* SMP-safe */
-@@ -741,6 +814,17 @@
- }
-
- /* SMP-safe */
-+int path_lookup_it(const char *path, unsigned flags, struct nameidata *nd,
-+ struct lookup_intent *it)
-+{
-+ int error = 0;
-+ if (path_init(path, flags, nd))
-+ error = path_walk_it(path, nd, it);
-+ return error;
-+}
-+
-+
-+/* SMP-safe */
- int path_lookup(const char *path, unsigned flags, struct nameidata *nd)
- {
- int error = 0;
-@@ -755,6 +839,7 @@
- {
- nd->last_type = LAST_ROOT; /* if there are only slashes... */
- nd->flags = flags;
-+ nd->intent = NULL;
- if (*name=='/')
- return walk_init_root(name,nd);
- read_lock(¤t->fs->lock);
-@@ -769,7 +854,8 @@
- * needs parent already locked. Doesn't follow mounts.
- * SMP-safe.
- */
--struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
-+struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base,
-+ struct nameidata *nd, struct lookup_intent *it)
- {
- struct dentry * dentry;
- struct inode *inode;
-@@ -792,13 +878,16 @@
- goto out;
- }
-
-- dentry = cached_lookup(base, name, 0);
-+ dentry = cached_lookup(base, name, 0, nd, it);
- if (!dentry) {
- struct dentry *new = d_alloc(base, name);
- dentry = ERR_PTR(-ENOMEM);
- if (!new)
- goto out;
- lock_kernel();
-+ if (inode->i_op->lookup_it)
-+ dentry = inode->i_op->lookup_it(inode, new, nd, it, 0);
-+ else
- dentry = inode->i_op->lookup(inode, new);
- unlock_kernel();
- if (!dentry)
-@@ -810,6 +899,13 @@
- return dentry;
- }
-
-+struct dentry * lookup_hash(struct qstr *name, struct dentry * base,
-+ struct nameidata *nd)
-+{
-+ return lookup_hash_it(name, base, nd, NULL);
-+}
-+
-+
- /* SMP-safe */
- struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
- {
-@@ -831,7 +927,7 @@
- }
- this.hash = end_name_hash(hash);
-
-- return lookup_hash(&this, base);
-+ return lookup_hash_it(&this, base, NULL, NULL);
- access:
- return ERR_PTR(-EACCES);
- }
-@@ -862,6 +958,23 @@
- return err;
- }
-
-+int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd,
-+ struct lookup_intent *it)
-+{
-+ char *tmp;
-+ int err;
-+
-+ tmp = getname(name);
-+ err = PTR_ERR(tmp);
-+ if (!IS_ERR(tmp)) {
-+ err = 0;
-+ if (path_init(tmp, flags, nd))
-+ err = path_walk_it(tmp, nd, it);
-+ putname(tmp);
-+ }
-+ return err;
-+}
-+
- /*
- * It's inline, so penalty for filesystems that don't use sticky bit is
- * minimal.
-@@ -957,7 +1070,8 @@
- return retval;
- }
-
--int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
-+static int vfs_create_it(struct inode *dir, struct dentry *dentry, int mode,
-+ struct lookup_intent *it)
- {
- int error;
-
-@@ -970,12 +1084,15 @@
- goto exit_lock;
-
- error = -EACCES; /* shouldn't it be ENOSYS? */
-- if (!dir->i_op || !dir->i_op->create)
-+ if (!dir->i_op || (!dir->i_op->create && !dir->i_op->create_it))
- goto exit_lock;
-
- DQUOT_INIT(dir);
- lock_kernel();
-- error = dir->i_op->create(dir, dentry, mode);
-+ if (dir->i_op->create_it)
-+ error = dir->i_op->create_it(dir, dentry, mode, it);
-+ else
-+ error = dir->i_op->create(dir, dentry, mode);
- unlock_kernel();
- exit_lock:
- up(&dir->i_zombie);
-@@ -984,6 +1101,11 @@
- return error;
- }
-
-+int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
-+{
-+ return vfs_create_it(dir, dentry, mode, NULL);
-+}
-+
- /*
- * open_namei()
- *
-@@ -998,7 +1120,8 @@
- * for symlinks (where the permissions are checked later).
- * SMP-safe
- */
--int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
-+int open_namei_it(const char *pathname, int flag, int mode,
-+ struct nameidata *nd, struct lookup_intent *it)
- {
- int acc_mode, error = 0;
- struct inode *inode;
-@@ -1008,11 +1131,14 @@
-
- acc_mode = ACC_MODE(flag);
-
-+ if (it)
-+ it->it_flags = flag;
-+
- /*
- * The simplest case - just a plain lookup.
- */
- if (!(flag & O_CREAT)) {
-- error = path_lookup(pathname, lookup_flags(flag), nd);
-+ error = path_lookup_it(pathname, lookup_flags(flag), nd, it);
- if (error)
- return error;
- dentry = nd->dentry;
-@@ -1022,6 +1148,10 @@
- /*
- * Create - we need to know the parent.
- */
-+ if (it) {
-+ it->it_create_mode = mode;
-+ it->it_op |= IT_CREAT;
-+ }
- error = path_lookup(pathname, LOOKUP_PARENT, nd);
- if (error)
- return error;
-@@ -1037,7 +1167,7 @@
-
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash_it(&nd->last, nd->dentry, nd, it);
-
- do_last:
- error = PTR_ERR(dentry);
-@@ -1046,10 +1176,11 @@
- goto exit;
- }
-
-+ it->it_create_mode = mode;
- /* Negative dentry, just create the file */
- if (!dentry->d_inode) {
-- error = vfs_create(dir->d_inode, dentry,
-- mode & ~current->fs->umask);
-+ error = vfs_create_it(dir->d_inode, dentry,
-+ mode & ~current->fs->umask, it);
- up(&dir->d_inode->i_sem);
- dput(nd->dentry);
- nd->dentry = dentry;
-@@ -1153,7 +1284,7 @@
- if (!error) {
- DQUOT_INIT(inode);
-
-- error = do_truncate(dentry, 0);
-+ error = do_truncate(dentry, 0, 1);
- }
- put_write_access(inode);
- if (error)
-@@ -1165,8 +1296,10 @@
- return 0;
-
- exit_dput:
-+ intent_release(it);
- dput(dentry);
- exit:
-+ intent_release(it);
- path_release(nd);
- return error;
-
-@@ -1185,7 +1318,10 @@
- * are done. Procfs-like symlinks just set LAST_BIND.
- */
- UPDATE_ATIME(dentry->d_inode);
-+ nd->intent = it;
- error = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (error)
-+ intent_release(it);
- dput(dentry);
- if (error)
- return error;
-@@ -1207,13 +1343,20 @@
- }
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash_it(&nd->last, nd->dentry, nd, it);
- putname(nd->last.name);
- goto do_last;
- }
-
-+int open_namei(const char *pathname, int flag, int mode, struct nameidata *nd)
-+{
-+ return open_namei_it(pathname, flag, mode, nd, NULL);
-+}
-+
-+
- /* SMP-safe */
--static struct dentry *lookup_create(struct nameidata *nd, int is_dir)
-+static struct dentry *lookup_create(struct nameidata *nd, int is_dir,
-+ struct lookup_intent *it)
- {
- struct dentry *dentry;
-
-@@ -1221,7 +1364,7 @@
- dentry = ERR_PTR(-EEXIST);
- if (nd->last_type != LAST_NORM)
- goto fail;
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash_it(&nd->last, nd->dentry, nd, it);
- if (IS_ERR(dentry))
- goto fail;
- if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-@@ -1277,7 +1420,20 @@
- error = path_lookup(tmp, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+
-+ if (nd.last_type != LAST_NORM) {
-+ error = -EEXIST;
-+ goto out2;
-+ }
-+ if (nd.dentry->d_inode->i_op->mknod_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->mknod_raw(&nd, mode, dev);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto out2;
-+ }
-+
-+ dentry = lookup_create(&nd, 0, NULL);
- error = PTR_ERR(dentry);
-
- mode &= ~current->fs->umask;
-@@ -1298,6 +1454,7 @@
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-+out2:
- path_release(&nd);
- out:
- putname(tmp);
-@@ -1345,7 +1502,18 @@
- error = path_lookup(tmp, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 1);
-+ if (nd.last_type != LAST_NORM) {
-+ error = -EEXIST;
-+ goto out2;
-+ }
-+ if (nd.dentry->d_inode->i_op->mkdir_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->mkdir_raw(&nd, mode);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto out2;
-+ }
-+ dentry = lookup_create(&nd, 1, NULL);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_mkdir(nd.dentry->d_inode, dentry,
-@@ -1353,6 +1521,7 @@
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-+out2:
- path_release(&nd);
- out:
- putname(tmp);
-@@ -1453,8 +1622,16 @@
- error = -EBUSY;
- goto exit1;
- }
-+ if (nd.dentry->d_inode->i_op->rmdir_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+
-+ error = op->rmdir_raw(&nd);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto exit1;
-+ }
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, &nd, NULL);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_rmdir(nd.dentry->d_inode, dentry);
-@@ -1512,8 +1689,15 @@
- error = -EISDIR;
- if (nd.last_type != LAST_NORM)
- goto exit1;
-+ if (nd.dentry->d_inode->i_op->unlink_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->unlink_raw(&nd);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto exit1;
-+ }
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, &nd, NULL);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- /* Why not before? Because we want correct error value */
-@@ -1580,15 +1764,27 @@
- error = path_lookup(to, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+ if (nd.last_type != LAST_NORM) {
-+ error = -EEXIST;
-+ goto out2;
-+ }
-+ if (nd.dentry->d_inode->i_op->symlink_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->symlink_raw(&nd, from);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto out2;
-+ }
-+ dentry = lookup_create(&nd, 0, NULL);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_symlink(nd.dentry->d_inode, dentry, from);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-+ out2:
- path_release(&nd);
--out:
-+ out:
- putname(to);
- }
- putname(from);
-@@ -1664,7 +1860,18 @@
- error = -EXDEV;
- if (old_nd.mnt != nd.mnt)
- goto out_release;
-- new_dentry = lookup_create(&nd, 0);
-+ if (nd.last_type != LAST_NORM) {
-+ error = -EEXIST;
-+ goto out_release;
-+ }
-+ if (nd.dentry->d_inode->i_op->link_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+ error = op->link_raw(&old_nd, &nd);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto out_release;
-+ }
-+ new_dentry = lookup_create(&nd, 0, NULL);
- error = PTR_ERR(new_dentry);
- if (!IS_ERR(new_dentry)) {
- error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
-@@ -1708,7 +1915,7 @@
- * locking].
- */
- int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry)
- {
- int error;
- struct inode *target;
-@@ -1787,7 +1994,7 @@
- }
-
- int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry)
- {
- int error;
-
-@@ -1875,9 +2082,18 @@
- if (newnd.last_type != LAST_NORM)
- goto exit2;
-
-+ if (old_dir->d_inode->i_op->rename_raw) {
-+ lock_kernel();
-+ error = old_dir->d_inode->i_op->rename_raw(&oldnd, &newnd);
-+ unlock_kernel();
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto exit2;
-+ }
-+
- double_lock(new_dir, old_dir);
-
-- old_dentry = lookup_hash(&oldnd.last, old_dir);
-+ old_dentry = lookup_hash_it(&oldnd.last, old_dir, &oldnd, NULL);
- error = PTR_ERR(old_dentry);
- if (IS_ERR(old_dentry))
- goto exit3;
-@@ -1893,16 +2109,16 @@
- if (newnd.last.name[newnd.last.len])
- goto exit4;
- }
-- new_dentry = lookup_hash(&newnd.last, new_dir);
-+ new_dentry = lookup_hash_it(&newnd.last, new_dir, &newnd, NULL);
- error = PTR_ERR(new_dentry);
- if (IS_ERR(new_dentry))
- goto exit4;
-
-+
- lock_kernel();
- error = vfs_rename(old_dir->d_inode, old_dentry,
- new_dir->d_inode, new_dentry);
- unlock_kernel();
--
- dput(new_dentry);
- exit4:
- dput(old_dentry);
-@@ -1953,20 +2169,26 @@
- }
-
- static inline int
--__vfs_follow_link(struct nameidata *nd, const char *link)
-+__vfs_follow_link(struct nameidata *nd, const char *link,
-+ struct lookup_intent *it)
- {
- int res = 0;
- char *name;
- if (IS_ERR(link))
- goto fail;
-
-+ if (it == NULL)
-+ it = nd->intent;
-+ else if (it != nd->intent)
-+ printk("it != nd->intent: tell phil@clusterfs.com\n");
-+
- if (*link == '/') {
- path_release(nd);
- if (!walk_init_root(link, nd))
- /* weird __emul_prefix() stuff did it */
- goto out;
- }
-- res = link_path_walk(link, nd);
-+ res = link_path_walk_it(link, nd, it);
- out:
- if (current->link_count || res || nd->last_type!=LAST_NORM)
- return res;
-@@ -1990,7 +2212,13 @@
-
- int vfs_follow_link(struct nameidata *nd, const char *link)
- {
-- return __vfs_follow_link(nd, link);
-+ return __vfs_follow_link(nd, link, NULL);
-+}
-+
-+int vfs_follow_link_it(struct nameidata *nd, const char *link,
-+ struct lookup_intent *it)
-+{
-+ return __vfs_follow_link(nd, link, it);
- }
-
- /* get the link contents into pagecache */
-@@ -2032,7 +2260,7 @@
- {
- struct page *page = NULL;
- char *s = page_getlink(dentry, &page);
-- int res = __vfs_follow_link(nd, s);
-+ int res = __vfs_follow_link(nd, s, NULL);
- if (page) {
- kunmap(page);
- page_cache_release(page);
-Index: lum/fs/namespace.c
-===================================================================
---- lum.orig/fs/namespace.c 2003-11-28 13:26:21.000000000 -0500
-+++ lum/fs/namespace.c 2004-06-07 17:19:43.000000000 -0400
-@@ -15,6 +15,7 @@
- #include <linux/quotaops.h>
- #include <linux/acct.h>
- #include <linux/module.h>
-+#include <linux/fs.h>
-
- #include <asm/uaccess.h>
-
-@@ -48,6 +49,7 @@
- INIT_LIST_HEAD(&mnt->mnt_child);
- INIT_LIST_HEAD(&mnt->mnt_mounts);
- INIT_LIST_HEAD(&mnt->mnt_list);
-+ INIT_LIST_HEAD(&mnt->mnt_lustre_list);
- if (name) {
- int size = strlen(name)+1;
- char * newname = kmalloc(size, GFP_KERNEL);
-@@ -98,6 +100,7 @@
- {
- old_nd->dentry = mnt->mnt_mountpoint;
- old_nd->mnt = mnt->mnt_parent;
-+ UNPIN(old_nd->dentry, old_nd->mnt, 1);
- mnt->mnt_parent = mnt;
- mnt->mnt_mountpoint = mnt->mnt_root;
- list_del_init(&mnt->mnt_child);
-@@ -109,6 +112,7 @@
- {
- mnt->mnt_parent = mntget(nd->mnt);
- mnt->mnt_mountpoint = dget(nd->dentry);
-+ PIN(nd->dentry, nd->mnt, 1);
- list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry));
- list_add_tail(&mnt->mnt_child, &nd->mnt->mnt_mounts);
- nd->dentry->d_mounted++;
-@@ -151,6 +155,9 @@
- {
- struct super_block *sb = mnt->mnt_sb;
- dput(mnt->mnt_root);
-+ spin_lock(&dcache_lock);
-+ list_del(&mnt->mnt_lustre_list);
-+ spin_unlock(&dcache_lock);
- free_vfsmnt(mnt);
- kill_super(sb);
- }
-@@ -286,7 +293,7 @@
- }
- }
-
--static int do_umount(struct vfsmount *mnt, int flags)
-+int do_umount(struct vfsmount *mnt, int flags)
- {
- struct super_block * sb = mnt->mnt_sb;
- int retval = 0;
-@@ -302,6 +309,8 @@
- */
-
- lock_kernel();
-+ if (sb->s_op->umount_lustre)
-+ sb->s_op->umount_lustre(sb);
- if( (flags&MNT_FORCE) && sb->s_op->umount_begin)
- sb->s_op->umount_begin(sb);
- unlock_kernel();
-@@ -488,14 +497,17 @@
- {
- struct nameidata old_nd;
- struct vfsmount *mnt = NULL;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
- int err = mount_is_safe(nd);
- if (err)
- return err;
- if (!old_name || !*old_name)
- return -EINVAL;
-- err = path_lookup(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd);
-- if (err)
-+ err = path_lookup_it(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd, &it);
-+ if (err) {
-+ intent_release(&it);
- return err;
-+ }
-
- down_write(¤t->namespace->sem);
- err = -EINVAL;
-@@ -518,6 +530,7 @@
- }
-
- up_write(¤t->namespace->sem);
-+ intent_release(&it);
- path_release(&old_nd);
- return err;
- }
-@@ -701,6 +714,7 @@
- unsigned long flags, void *data_page)
- {
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
- int retval = 0;
- int mnt_flags = 0;
-
-@@ -725,9 +739,11 @@
- flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV);
-
- /* ... and get the mountpoint */
-- retval = path_lookup(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd);
-- if (retval)
-+ retval = path_lookup_it(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it);
-+ if (retval) {
-+ intent_release(&it);
- return retval;
-+ }
-
- if (flags & MS_REMOUNT)
- retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
-@@ -739,6 +755,8 @@
- else
- retval = do_add_mount(&nd, type_page, flags, mnt_flags,
- dev_name, data_page);
-+
-+ intent_release(&it);
- path_release(&nd);
- return retval;
- }
-@@ -904,6 +922,8 @@
- {
- struct vfsmount *tmp;
- struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd;
-+ struct lookup_intent new_it = { .it_op = IT_GETATTR };
-+ struct lookup_intent old_it = { .it_op = IT_GETATTR };
- int error;
-
- if (!capable(CAP_SYS_ADMIN))
-@@ -911,14 +931,14 @@
-
- lock_kernel();
-
-- error = __user_walk(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd);
-+ error = __user_walk_it(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd, &new_it);
- if (error)
- goto out0;
- error = -EINVAL;
- if (!check_mnt(new_nd.mnt))
- goto out1;
-
-- error = __user_walk(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd);
-+ error = __user_walk_it(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd, &old_it);
- if (error)
- goto out1;
-
-@@ -973,8 +993,10 @@
- up(&old_nd.dentry->d_inode->i_zombie);
- up_write(¤t->namespace->sem);
- path_release(&user_nd);
-+ intent_release(&old_it);
- path_release(&old_nd);
- out1:
-+ intent_release(&new_it);
- path_release(&new_nd);
- out0:
- unlock_kernel();
-Index: lum/fs/open.c
-===================================================================
---- lum.orig/fs/open.c 2003-08-25 07:44:43.000000000 -0400
-+++ lum/fs/open.c 2004-06-07 17:19:43.000000000 -0400
-@@ -19,6 +19,8 @@
- #include <asm/uaccess.h>
-
- #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
-+extern int path_walk_it(const char *name, struct nameidata *nd,
-+ struct lookup_intent *it);
-
- int vfs_statfs(struct super_block *sb, struct statfs *buf)
- {
-@@ -95,9 +97,10 @@
- write_unlock(&files->file_lock);
- }
-
--int do_truncate(struct dentry *dentry, loff_t length)
-+int do_truncate(struct dentry *dentry, loff_t length, int called_from_open)
- {
- struct inode *inode = dentry->d_inode;
-+ struct inode_operations *op = dentry->d_inode->i_op;
- int error;
- struct iattr newattrs;
-
-@@ -109,7 +112,13 @@
- down(&inode->i_sem);
- newattrs.ia_size = length;
- newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
-- error = notify_change(dentry, &newattrs);
-+ if (called_from_open)
-+ newattrs.ia_valid |= ATTR_FROM_OPEN;
-+ if (op->setattr_raw) {
-+ newattrs.ia_valid |= ATTR_RAW;
-+ error = op->setattr_raw(inode, &newattrs);
-+ } else
-+ error = notify_change(dentry, &newattrs);
- up(&inode->i_sem);
- up_write(&inode->i_alloc_sem);
- return error;
-@@ -120,12 +129,13 @@
- struct nameidata nd;
- struct inode * inode;
- int error;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
- error = -EINVAL;
- if (length < 0) /* sorry, but loff_t says... */
- goto out;
-
-- error = user_path_walk(path, &nd);
-+ error = user_path_walk_it(path, &nd, &it);
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-@@ -165,11 +175,13 @@
- error = locks_verify_truncate(inode, NULL, length);
- if (!error) {
- DQUOT_INIT(inode);
-- error = do_truncate(nd.dentry, length);
-+ intent_release(&it);
-+ error = do_truncate(nd.dentry, length, 0);
- }
- put_write_access(inode);
-
- dput_and_out:
-+ intent_release(&it);
- path_release(&nd);
- out:
- return error;
-@@ -217,7 +229,7 @@
-
- error = locks_verify_truncate(inode, file, length);
- if (!error)
-- error = do_truncate(dentry, length);
-+ error = do_truncate(dentry, length, 0);
- out_putf:
- fput(file);
- out:
-@@ -262,11 +274,13 @@
- struct inode * inode;
- struct iattr newattrs;
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, NULL);
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-
-+ /* this is safe without a Lustre lock because it only depends
-+ on the super block */
- error = -EROFS;
- if (IS_RDONLY(inode))
- goto dput_and_out;
-@@ -281,11 +295,25 @@
- goto dput_and_out;
-
- newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
-- } else {
-+ }
-+
-+ if (inode->i_op->setattr_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+
-+ newattrs.ia_valid |= ATTR_RAW;
-+ error = op->setattr_raw(inode, &newattrs);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto dput_and_out;
-+ }
-+
-+ error = -EPERM;
-+ if (!times) {
- if (current->fsuid != inode->i_uid &&
- (error = permission(inode,MAY_WRITE)) != 0)
- goto dput_and_out;
- }
-+
- error = notify_change(nd.dentry, &newattrs);
- dput_and_out:
- path_release(&nd);
-@@ -306,12 +334,14 @@
- struct inode * inode;
- struct iattr newattrs;
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, NULL);
-
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-
-+ /* this is safe without a Lustre lock because it only depends
-+ on the super block */
- error = -EROFS;
- if (IS_RDONLY(inode))
- goto dput_and_out;
-@@ -326,7 +356,20 @@
- newattrs.ia_atime = times[0].tv_sec;
- newattrs.ia_mtime = times[1].tv_sec;
- newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
-- } else {
-+ }
-+
-+ if (inode->i_op->setattr_raw) {
-+ struct inode_operations *op = nd.dentry->d_inode->i_op;
-+
-+ newattrs.ia_valid |= ATTR_RAW;
-+ error = op->setattr_raw(inode, &newattrs);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ goto dput_and_out;
-+ }
-+
-+ error = -EPERM;
-+ if (!utimes) {
- if (current->fsuid != inode->i_uid &&
- (error = permission(inode,MAY_WRITE)) != 0)
- goto dput_and_out;
-@@ -349,6 +392,7 @@
- int old_fsuid, old_fsgid;
- kernel_cap_t old_cap;
- int res;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
- if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
- return -EINVAL;
-@@ -366,13 +410,14 @@
- else
- current->cap_effective = current->cap_permitted;
-
-- res = user_path_walk(filename, &nd);
-+ res = user_path_walk_it(filename, &nd, &it);
- if (!res) {
- res = permission(nd.dentry->d_inode, mode);
- /* SuS v2 requires we report a read only fs too */
- if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
- && !special_file(nd.dentry->d_inode->i_mode))
- res = -EROFS;
-+ intent_release(&it);
- path_release(&nd);
- }
-
-@@ -387,8 +432,9 @@
- {
- int error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_CHDIR };
-
-- error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd);
-+ error = __user_walk_it(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd, &it);
- if (error)
- goto out;
-
-@@ -399,6 +445,7 @@
- set_fs_pwd(current->fs, nd.mnt, nd.dentry);
-
- dput_and_out:
-+ intent_release(&it);
- path_release(&nd);
- out:
- return error;
-@@ -438,9 +485,10 @@
- {
- int error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-- error = __user_walk(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
-- LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
-+ error = __user_walk_it(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
-+ LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd, &it);
- if (error)
- goto out;
-
-@@ -456,39 +504,56 @@
- set_fs_altroot();
- error = 0;
- dput_and_out:
-+ intent_release(&it);
- path_release(&nd);
- out:
- return error;
- }
-
--asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
-+int chmod_common(struct dentry *dentry, mode_t mode)
- {
-- struct inode * inode;
-- struct dentry * dentry;
-- struct file * file;
-- int err = -EBADF;
-+ struct inode *inode = dentry->d_inode;
- struct iattr newattrs;
-+ int err = -EROFS;
-
-- file = fget(fd);
-- if (!file)
-+ if (IS_RDONLY(inode))
- goto out;
-
-- dentry = file->f_dentry;
-- inode = dentry->d_inode;
-+ if (inode->i_op->setattr_raw) {
-+ newattrs.ia_mode = mode;
-+ newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-+ newattrs.ia_valid |= ATTR_RAW;
-+ err = inode->i_op->setattr_raw(inode, &newattrs);
-+ /* the file system wants to use normal vfs path now */
-+ if (err != -EOPNOTSUPP)
-+ goto out;
-+ }
-
-- err = -EROFS;
-- if (IS_RDONLY(inode))
-- goto out_putf;
- err = -EPERM;
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-- goto out_putf;
-+ goto out;
-+
- if (mode == (mode_t) -1)
- mode = inode->i_mode;
- newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
- newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
- err = notify_change(dentry, &newattrs);
-
--out_putf:
-+out:
-+ return err;
-+}
-+
-+asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
-+{
-+ struct file * file;
-+ int err = -EBADF;
-+
-+ file = fget(fd);
-+ if (!file)
-+ goto out;
-+
-+ err = chmod_common(file->f_dentry, mode);
-+
- fput(file);
- out:
- return err;
-@@ -497,30 +562,14 @@
- asmlinkage long sys_chmod(const char * filename, mode_t mode)
- {
- struct nameidata nd;
-- struct inode * inode;
- int error;
-- struct iattr newattrs;
-
- error = user_path_walk(filename, &nd);
- if (error)
- goto out;
-- inode = nd.dentry->d_inode;
--
-- error = -EROFS;
-- if (IS_RDONLY(inode))
-- goto dput_and_out;
-
-- error = -EPERM;
-- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-- goto dput_and_out;
-+ error = chmod_common(nd.dentry, mode);
-
-- if (mode == (mode_t) -1)
-- mode = inode->i_mode;
-- newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
-- newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-- error = notify_change(nd.dentry, &newattrs);
--
--dput_and_out:
- path_release(&nd);
- out:
- return error;
-@@ -540,6 +589,20 @@
- error = -EROFS;
- if (IS_RDONLY(inode))
- goto out;
-+
-+ if (inode->i_op->setattr_raw) {
-+ struct inode_operations *op = dentry->d_inode->i_op;
-+
-+ newattrs.ia_uid = user;
-+ newattrs.ia_gid = group;
-+ newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
-+ newattrs.ia_valid |= ATTR_RAW;
-+ error = op->setattr_raw(inode, &newattrs);
-+ /* the file system wants to use normal vfs path now */
-+ if (error != -EOPNOTSUPP)
-+ return error;
-+ }
-+
- error = -EPERM;
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
- goto out;
-@@ -644,6 +707,7 @@
- {
- int namei_flags, error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_OPEN };
-
- namei_flags = flags;
- if ((namei_flags+1) & O_ACCMODE)
-@@ -651,14 +715,15 @@
- if (namei_flags & O_TRUNC)
- namei_flags |= 2;
-
-- error = open_namei(filename, namei_flags, mode, &nd);
-- if (!error)
-- return dentry_open(nd.dentry, nd.mnt, flags);
-+ error = open_namei_it(filename, namei_flags, mode, &nd, &it);
-+ if (error)
-+ return ERR_PTR(error);
-
-- return ERR_PTR(error);
-+ return dentry_open_it(nd.dentry, nd.mnt, flags, &it);
- }
-
--struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
-+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
-+ int flags, struct lookup_intent *it)
- {
- struct file * f;
- struct inode *inode;
-@@ -695,12 +760,15 @@
- }
-
- if (f->f_op && f->f_op->open) {
-+ f->f_it = it;
- error = f->f_op->open(inode,f);
-+ f->f_it = NULL;
- if (error)
- goto cleanup_all;
- }
- f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
-
-+ intent_release(it);
- return f;
-
- cleanup_all:
-@@ -715,11 +783,17 @@
- cleanup_file:
- put_filp(f);
- cleanup_dentry:
-+ intent_release(it);
- dput(dentry);
- mntput(mnt);
- return ERR_PTR(error);
- }
-
-+struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
-+{
-+ return dentry_open_it(dentry, mnt, flags, NULL);
-+}
-+
- /*
- * Find an empty file descriptor entry, and mark it busy.
- */
-Index: lum/fs/stat.c
-===================================================================
---- lum.orig/fs/stat.c 2003-08-25 07:44:43.000000000 -0400
-+++ lum/fs/stat.c 2004-06-07 17:19:43.000000000 -0400
-@@ -17,10 +17,12 @@
- * Revalidate the inode. This is required for proper NFS attribute caching.
- */
- static __inline__ int
--do_revalidate(struct dentry *dentry)
-+do_revalidate(struct dentry *dentry, struct lookup_intent *it)
- {
- struct inode * inode = dentry->d_inode;
-- if (inode->i_op && inode->i_op->revalidate)
-+ if (inode->i_op && inode->i_op->revalidate_it)
-+ return inode->i_op->revalidate_it(dentry, it);
-+ else if (inode->i_op && inode->i_op->revalidate)
- return inode->i_op->revalidate(dentry);
- return 0;
- }
-@@ -137,13 +139,15 @@
- asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf)
- {
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
- int error;
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (!error) {
-- error = do_revalidate(nd.dentry);
-+ error = do_revalidate(nd.dentry, &it);
- if (!error)
- error = cp_old_stat(nd.dentry->d_inode, statbuf);
-+ intent_release(&it);
- path_release(&nd);
- }
- return error;
-@@ -153,13 +157,15 @@
- asmlinkage long sys_newstat(char * filename, struct stat * statbuf)
- {
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
- int error;
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (!error) {
-- error = do_revalidate(nd.dentry);
-+ error = do_revalidate(nd.dentry, &it);
- if (!error)
- error = cp_new_stat(nd.dentry->d_inode, statbuf);
-+ intent_release(&it);
- path_release(&nd);
- }
- return error;
-@@ -174,13 +180,15 @@
- asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf)
- {
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
- int error;
-
-- error = user_path_walk_link(filename, &nd);
-+ error = user_path_walk_link_it(filename, &nd, &it);
- if (!error) {
-- error = do_revalidate(nd.dentry);
-+ error = do_revalidate(nd.dentry, &it);
- if (!error)
- error = cp_old_stat(nd.dentry->d_inode, statbuf);
-+ intent_release(&it);
- path_release(&nd);
- }
- return error;
-@@ -191,13 +199,15 @@
- asmlinkage long sys_newlstat(char * filename, struct stat * statbuf)
- {
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
- int error;
-
-- error = user_path_walk_link(filename, &nd);
-+ error = user_path_walk_link_it(filename, &nd, &it);
- if (!error) {
-- error = do_revalidate(nd.dentry);
-+ error = do_revalidate(nd.dentry, &it);
- if (!error)
- error = cp_new_stat(nd.dentry->d_inode, statbuf);
-+ intent_release(&it);
- path_release(&nd);
- }
- return error;
-@@ -218,7 +228,7 @@
- if (f) {
- struct dentry * dentry = f->f_dentry;
-
-- err = do_revalidate(dentry);
-+ err = do_revalidate(dentry, NULL);
- if (!err)
- err = cp_old_stat(dentry->d_inode, statbuf);
- fput(f);
-@@ -237,7 +247,7 @@
- if (f) {
- struct dentry * dentry = f->f_dentry;
-
-- err = do_revalidate(dentry);
-+ err = do_revalidate(dentry, NULL);
- if (!err)
- err = cp_new_stat(dentry->d_inode, statbuf);
- fput(f);
-@@ -259,7 +269,7 @@
-
- error = -EINVAL;
- if (inode->i_op && inode->i_op->readlink &&
-- !(error = do_revalidate(nd.dentry))) {
-+ !(error = do_revalidate(nd.dentry, NULL))) {
- UPDATE_ATIME(inode);
- error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
- }
-@@ -335,12 +345,14 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (!error) {
-- error = do_revalidate(nd.dentry);
-+ error = do_revalidate(nd.dentry, &it);
- if (!error)
- error = cp_new_stat64(nd.dentry->d_inode, statbuf);
-+ intent_release(&it);
- path_release(&nd);
- }
- return error;
-@@ -350,12 +362,14 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-- error = user_path_walk_link(filename, &nd);
-+ error = user_path_walk_link_it(filename, &nd, &it);
- if (!error) {
-- error = do_revalidate(nd.dentry);
-+ error = do_revalidate(nd.dentry, &it);
- if (!error)
- error = cp_new_stat64(nd.dentry->d_inode, statbuf);
-+ intent_release(&it);
- path_release(&nd);
- }
- return error;
-@@ -370,7 +384,7 @@
- if (f) {
- struct dentry * dentry = f->f_dentry;
-
-- err = do_revalidate(dentry);
-+ err = do_revalidate(dentry, NULL);
- if (!err)
- err = cp_new_stat64(dentry->d_inode, statbuf);
- fput(f);
-Index: lum/include/linux/dcache.h
-===================================================================
---- lum.orig/include/linux/dcache.h 2002-11-28 18:53:15.000000000 -0500
-+++ lum/include/linux/dcache.h 2004-06-07 17:19:44.000000000 -0400
-@@ -6,6 +6,52 @@
- #include <asm/atomic.h>
- #include <linux/mount.h>
- #include <linux/kernel.h>
-+#include <linux/string.h>
-+
-+#define IT_OPEN 0x0001
-+#define IT_CREAT 0x0002
-+#define IT_READDIR 0x0004
-+#define IT_GETATTR 0x0008
-+#define IT_LOOKUP 0x0010
-+#define IT_UNLINK 0x0020
-+#define IT_GETXATTR 0x0040
-+#define IT_EXEC 0x0080
-+#define IT_PIN 0x0100
-+#define IT_CHDIR 0x0200
-+
-+#define IT_FL_LOCKED 0x0001
-+#define IT_FL_FOLLOWED 0x0002 /* set by vfs_follow_link */
-+
-+#define INTENT_MAGIC 0x19620323
-+
-+
-+struct lustre_intent_data {
-+ int it_disposition;
-+ int it_status;
-+ __u64 it_lock_handle;
-+ void *it_data;
-+ int it_lock_mode;
-+ int it_int_flags;
-+};
-+struct lookup_intent {
-+ int it_magic;
-+ void (*it_op_release)(struct lookup_intent *);
-+ int it_op;
-+ int it_flags;
-+ int it_create_mode;
-+ union {
-+ struct lustre_intent_data lustre;
-+ } d;
-+};
-+
-+static inline void intent_init(struct lookup_intent *it, int op, int flags)
-+{
-+ memset(it, 0, sizeof(*it));
-+ it->it_magic = INTENT_MAGIC;
-+ it->it_op = op;
-+ it->it_flags = flags;
-+}
-+
-
- /*
- * linux/include/linux/dcache.h
-@@ -84,6 +130,8 @@
- unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */
- };
-
-+struct nameidata;
-+
- struct dentry_operations {
- int (*d_revalidate)(struct dentry *, int);
- int (*d_hash) (struct dentry *, struct qstr *);
-@@ -91,8 +139,22 @@
- int (*d_delete)(struct dentry *);
- void (*d_release)(struct dentry *);
- void (*d_iput)(struct dentry *, struct inode *);
-+ int (*d_revalidate_it)(struct dentry *, int, struct nameidata *, struct lookup_intent *);
-+ void (*d_pin)(struct dentry *, struct vfsmount * , int);
-+ void (*d_unpin)(struct dentry *, struct vfsmount *, int);
- };
-
-+#define PIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_pin) \
-+ de->d_op->d_pin(de, mnt, flag);
-+#define UNPIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_unpin) \
-+ de->d_op->d_unpin(de, mnt, flag);
-+
-+
-+/* defined in fs/namei.c */
-+extern void intent_release(struct lookup_intent *it);
-+/* defined in fs/dcache.c */
-+extern void __d_rehash(struct dentry * entry, int lock);
-+
- /* the dentry parameter passed to d_hash and d_compare is the parent
- * directory of the entries to be compared. It is used in case these
- * functions need any directory specific information for determining
-@@ -124,6 +186,7 @@
- * s_nfsd_free_path semaphore will be down
- */
- #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */
-+#define DCACHE_LUSTRE_INVALID 0x0010 /* Lustre invalidated */
-
- extern spinlock_t dcache_lock;
-
-Index: lum/include/linux/fs.h
-===================================================================
---- lum.orig/include/linux/fs.h 2004-06-03 16:32:26.000000000 -0400
-+++ lum/include/linux/fs.h 2004-06-07 17:24:37.000000000 -0400
-@@ -73,6 +73,7 @@
-
- #define FMODE_READ 1
- #define FMODE_WRITE 2
-+#define FMODE_EXEC 4
-
- #define READ 0
- #define WRITE 1
-@@ -340,6 +341,9 @@
- #define ATTR_MTIME_SET 256
- #define ATTR_FORCE 512 /* Not a change, but a change it */
- #define ATTR_ATTR_FLAG 1024
-+#define ATTR_RAW 0x0800 /* file system, not vfs will massage attrs */
-+#define ATTR_FROM_OPEN 0x1000 /* called from open path, ie O_TRUNC */
-+#define ATTR_CTIME_SET 0x2000
-
- /*
- * This is the Inode Attributes structure, used for notify_change(). It
-@@ -478,6 +482,7 @@
- struct pipe_inode_info *i_pipe;
- struct block_device *i_bdev;
- struct char_device *i_cdev;
-+ void *i_filterdata;
-
- unsigned long i_dnotify_mask; /* Directory notify events */
- struct dnotify_struct *i_dnotify; /* for directory notifications */
-@@ -582,6 +587,7 @@
-
- /* needed for tty driver, and maybe others */
- void *private_data;
-+ struct lookup_intent *f_it;
-
- /* preallocated helper kiobuf to speedup O_DIRECT */
- struct kiobuf *f_iobuf;
-@@ -702,6 +708,7 @@
- struct qstr last;
- unsigned int flags;
- int last_type;
-+ struct lookup_intent *intent;
- };
-
- /*
-@@ -822,7 +829,8 @@
- extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
- extern int vfs_rmdir(struct inode *, struct dentry *);
- extern int vfs_unlink(struct inode *, struct dentry *);
--extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
-+int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-+ struct inode *new_dir, struct dentry *new_dentry);
-
- /*
- * File types
-@@ -884,21 +892,32 @@
-
- struct inode_operations {
- int (*create) (struct inode *,struct dentry *,int);
-+ int (*create_it) (struct inode *,struct dentry *,int, struct lookup_intent *);
- struct dentry * (*lookup) (struct inode *,struct dentry *);
-+ struct dentry * (*lookup_it) (struct inode *,struct dentry *, struct nameidata *, struct lookup_intent *, int flags);
- int (*link) (struct dentry *,struct inode *,struct dentry *);
-+ int (*link_raw) (struct nameidata *,struct nameidata *);
- int (*unlink) (struct inode *,struct dentry *);
-+ int (*unlink_raw) (struct nameidata *);
- int (*symlink) (struct inode *,struct dentry *,const char *);
-+ int (*symlink_raw) (struct nameidata *,const char *);
- int (*mkdir) (struct inode *,struct dentry *,int);
-+ int (*mkdir_raw) (struct nameidata *,int);
- int (*rmdir) (struct inode *,struct dentry *);
-+ int (*rmdir_raw) (struct nameidata *);
- int (*mknod) (struct inode *,struct dentry *,int,int);
-+ int (*mknod_raw) (struct nameidata *,int,dev_t);
- int (*rename) (struct inode *, struct dentry *,
- struct inode *, struct dentry *);
-+ int (*rename_raw) (struct nameidata *, struct nameidata *);
- int (*readlink) (struct dentry *, char *,int);
- int (*follow_link) (struct dentry *, struct nameidata *);
- void (*truncate) (struct inode *);
- int (*permission) (struct inode *, int);
- int (*revalidate) (struct dentry *);
-+ int (*revalidate_it) (struct dentry *, struct lookup_intent *);
- int (*setattr) (struct dentry *, struct iattr *);
-+ int (*setattr_raw) (struct inode *, struct iattr *);
- int (*getattr) (struct dentry *, struct iattr *);
- int (*setxattr) (struct dentry *, const char *, void *, size_t, int);
- ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
-@@ -938,6 +957,7 @@
- int (*remount_fs) (struct super_block *, int *, char *);
- void (*clear_inode) (struct inode *);
- void (*umount_begin) (struct super_block *);
-+ void (*umount_lustre) (struct super_block *);
-
- /* Following are for knfsd to interact with "interesting" filesystems
- * Currently just reiserfs, but possibly FAT and others later
-@@ -1094,10 +1114,14 @@
-
- asmlinkage long sys_open(const char *, int, int);
- asmlinkage long sys_close(unsigned int); /* yes, it's really unsigned */
--extern int do_truncate(struct dentry *, loff_t start);
-+extern int do_truncate(struct dentry *, loff_t start, int called_from_open);
-
- extern struct file *filp_open(const char *, int, int);
- extern struct file * dentry_open(struct dentry *, struct vfsmount *, int);
-+extern int open_namei_it(const char *filename, int namei_flags, int mode,
-+ struct nameidata *nd, struct lookup_intent *it);
-+extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
-+ int flags, struct lookup_intent *it);
- extern int filp_close(struct file *, fl_owner_t id);
- extern char * getname(const char *);
-
-@@ -1386,6 +1410,7 @@
- extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
-
- extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *));
-+extern int FASTCALL(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it));
- extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *));
- extern int FASTCALL(path_walk(const char *, struct nameidata *));
- extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
-@@ -1394,9 +1419,11 @@
- extern int follow_down(struct vfsmount **, struct dentry **);
- extern int follow_up(struct vfsmount **, struct dentry **);
- extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
--extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
-+extern struct dentry * lookup_hash(struct qstr *, struct dentry *, struct nameidata *);
- #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
- #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
-+#define user_path_walk_it(name,nd,it) __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it)
-+#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it)
-
- extern void inode_init_once(struct inode *);
- extern void iput(struct inode *);
-@@ -1500,6 +1527,8 @@
-
- extern int vfs_readlink(struct dentry *, char *, int, const char *);
- extern int vfs_follow_link(struct nameidata *, const char *);
-+extern int vfs_follow_link_it(struct nameidata *, const char *,
-+ struct lookup_intent *it);
- extern int page_readlink(struct dentry *, char *, int);
- extern int page_follow_link(struct dentry *, struct nameidata *);
- extern struct inode_operations page_symlink_inode_operations;
-Index: lum/include/linux/fs_struct.h
-===================================================================
---- lum.orig/include/linux/fs_struct.h 2001-07-13 18:10:44.000000000 -0400
-+++ lum/include/linux/fs_struct.h 2004-06-07 17:19:44.000000000 -0400
-@@ -34,10 +34,12 @@
- write_lock(&fs->lock);
- old_root = fs->root;
- old_rootmnt = fs->rootmnt;
-+ PIN(dentry, mnt, 1);
- fs->rootmnt = mntget(mnt);
- fs->root = dget(dentry);
- write_unlock(&fs->lock);
- if (old_root) {
-+ UNPIN(old_root, old_rootmnt, 1);
- dput(old_root);
- mntput(old_rootmnt);
- }
-@@ -57,10 +59,12 @@
- write_lock(&fs->lock);
- old_pwd = fs->pwd;
- old_pwdmnt = fs->pwdmnt;
-+ PIN(dentry, mnt, 0);
- fs->pwdmnt = mntget(mnt);
- fs->pwd = dget(dentry);
- write_unlock(&fs->lock);
- if (old_pwd) {
-+ UNPIN(old_pwd, old_pwdmnt, 0);
- dput(old_pwd);
- mntput(old_pwdmnt);
- }
-Index: lum/include/linux/mount.h
-===================================================================
---- lum.orig/include/linux/mount.h 2001-10-05 16:05:55.000000000 -0400
-+++ lum/include/linux/mount.h 2004-06-07 17:19:44.000000000 -0400
-@@ -29,6 +29,8 @@
- int mnt_flags;
- char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */
- struct list_head mnt_list;
-+ struct list_head mnt_lustre_list; /* GNS mount list */
-+ unsigned long mnt_last_used; /* for GNS auto-umount (jiffies) */
- };
-
- static inline struct vfsmount *mntget(struct vfsmount *mnt)
-@@ -39,6 +41,7 @@
- }
-
- extern void __mntput(struct vfsmount *mnt);
-+extern int do_umount(struct vfsmount *mnt, int flags);
-
- static inline void mntput(struct vfsmount *mnt)
- {
-Index: lum/kernel/exit.c
-===================================================================
---- lum.orig/kernel/exit.c 2002-11-28 18:53:15.000000000 -0500
-+++ lum/kernel/exit.c 2004-06-07 17:19:44.000000000 -0400
-@@ -238,11 +238,14 @@
- {
- /* No need to hold fs->lock if we are killing it */
- if (atomic_dec_and_test(&fs->count)) {
-+ UNPIN(fs->pwd, fs->pwdmnt, 0);
-+ UNPIN(fs->root, fs->rootmnt, 1);
- dput(fs->root);
- mntput(fs->rootmnt);
- dput(fs->pwd);
- mntput(fs->pwdmnt);
- if (fs->altroot) {
-+ UNPIN(fs->altroot, fs->altrootmnt, 1);
- dput(fs->altroot);
- mntput(fs->altrootmnt);
- }
-Index: lum/kernel/fork.c
-===================================================================
---- lum.orig/kernel/fork.c 2003-11-28 13:26:21.000000000 -0500
-+++ lum/kernel/fork.c 2004-06-07 17:19:44.000000000 -0400
-@@ -386,10 +386,13 @@
- fs->umask = old->umask;
- read_lock(&old->lock);
- fs->rootmnt = mntget(old->rootmnt);
-+ PIN(old->pwd, old->pwdmnt, 0);
-+ PIN(old->root, old->rootmnt, 1);
- fs->root = dget(old->root);
- fs->pwdmnt = mntget(old->pwdmnt);
- fs->pwd = dget(old->pwd);
- if (old->altroot) {
-+ PIN(old->altroot, old->altrootmnt, 1);
- fs->altrootmnt = mntget(old->altrootmnt);
- fs->altroot = dget(old->altroot);
- } else {
-Index: lum/kernel/ksyms.c
-===================================================================
---- lum.orig/kernel/ksyms.c 2004-06-03 16:32:26.000000000 -0400
-+++ lum/kernel/ksyms.c 2004-06-07 17:25:11.000000000 -0400
-@@ -275,6 +275,8 @@
- EXPORT_SYMBOL(mark_page_accessed);
- EXPORT_SYMBOL(vfs_readlink);
- EXPORT_SYMBOL(vfs_follow_link);
-+EXPORT_SYMBOL(vfs_follow_link_it);
-+EXPORT_SYMBOL(do_umount);
- EXPORT_SYMBOL(page_readlink);
- EXPORT_SYMBOL(page_follow_link);
- EXPORT_SYMBOL(page_symlink_inode_operations);
-Index: lum/net/unix/af_unix.c
-===================================================================
---- lum.orig/net/unix/af_unix.c 2002-11-28 18:53:16.000000000 -0500
-+++ lum/net/unix/af_unix.c 2004-06-07 17:19:44.000000000 -0400
-@@ -703,7 +703,7 @@
- /*
- * Do the final lookup.
- */
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash(&nd.last, nd.dentry, &nd);
- err = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- goto out_mknod_unlock;
-Index: lum/drivers/hotplug/pci_hotplug_core.c
-===================================================================
---- lum.orig/drivers/hotplug/pci_hotplug_core.c 2003-11-28 13:26:20.000000000 -0500
-+++ lum/drivers/hotplug/pci_hotplug_core.c 2004-06-08 01:59:32.000000000 -0400
-@@ -478,7 +478,7 @@
-
- down(&parent->d_inode->i_sem);
-
-- d = lookup_hash(&qstr,parent);
-+ d = lookup_hash(&qstr,parent,NULL);
-
- error = PTR_ERR(d);
- if (!IS_ERR(d)) {
+++ /dev/null
-uml-patch-2.4.24-1.patch
-uml-2.4.24-do_mmap_pgoff-fix.patch
-uml-export-end_iomem-2.4.24.patch
-configurable-x86-stack-2.4.24.patch
-dev_read_only-2.4.24.patch
-exports-2.4.24.patch
-lustre_version.patch
-vfs_intent-2.4.24.patch
-invalidate_show-2.4.24.patch
-export-truncate-2.4.24.patch
-iod-stock-exports-2.4.24.patch
-ext3-htree-2.4.24.patch
-linux-2.4.24-xattr-0.8.54.patch
-ext3-orphan_lock-2.4.24.patch
-ext3-noread-2.4.24.patch
-ext3-delete_thread-2.4.24.patch
-extN-wantedi-2.4.24.patch
-ext3-san-2.4.24.patch
-ext3-map_inode_page-2.4.24.patch
-ext3-error-export-2.4.24.patch
-iopen-2.4.24.patch
-tcp-zero-copy-2.4.24.patch
-jbd-dont-account-blocks-twice-2.4.24.patch
-jbd-commit-tricks-2.4.24.patch
-ext3-no-write-super-2.4.24.patch
-add_page_private-2.4.24.patch
-nfs_export_kernel-2.4.24.patch
-ext3-ea-in-inode-2.4.24.patch
-listman-2.4.24.patch
-ext3-trusted_ea-2.4.24.patch
-ext3-extents-2.4.24.patch
-ext3-extents-in-ea-2.4.24.patch
-ext3-extents-in-ea-ioctl-2.4.24.patch
-ext3-extents-in-ea-exports-symbol-2.4.24.patch
-kernel_text_address-2.4.24-vanilla.patch
-gfp_memalloc-2.4.24.patch
-ext3-xattr-ptr-arith-fix-2.4.24.patch
-3.5G-address-space-2.4.24-vanilla.patch
-procfs-ndynamic-2.4.24.patch
-ext3-truncate-buffer-head-2.4.24.patch
-inode-max-readahead-2.4.24.patch
-dynamic-locks-2.4.24.patch
-vfs-pdirops-2.4.24.patch
-ext3-pdirops-2.4.24-chaos.patch
-ext3-mds-num-2.4.24.patch
-export_lookup_create-2.4.24.patch
-ext3-raw-lookup-pdirops-2.4.24.patch
-kksymoops-2.4.24.vanilla.patch
-ext3-inode-reuse-2.4.24.patch
-export-zap-page-range-2.4.24.patch
-export_num_siblings-2.4.24.patch
-ext3-nlinks-2.4.24.patch
-ext3-dentry-fid-2.4.24.patch