Merge branch 'for-linus/2635-updates' of git://git.fluff.org/bjdooks/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 28 May 2010 17:19:03 +0000 (10:19 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 28 May 2010 17:19:03 +0000 (10:19 -0700)
* 'for-linus/2635-updates' of git://git.fluff.org/bjdooks/linux:
  ARM: S5PV210: serial: Fix section mismatch warning
  ARM: s3c2410_defconfig: Add new machines
  ARM: s3c6400_defconfig: Add framebuffer and basic LCD
  ARM: s3c6400_defconfig: Add RTC driver support
  ARM: s3c6400_defconfig: Enable USB host side
  ARM: s3c6400_defconfig: Add SPI driver
  ARM: s3c6400_defconfig: Update compiled machines
  ARM: S5P: Regoster clk_xusbxti clock for hsotg driver
  ARM: S3C64XX: Add USB OTG HCLK to the list of clocks
  ARM: SAMSUNG: gpio-cfg.h: update documentation
  ARM: SAMSUNG: Documentation: add documentation on GPIO code
  ARM: SAMSUNG: Fix documentation for s3c_gpio_cfgpin()
  ARM: S3C24XX: Documentation: add section on gpiolib changes
  ARM: S3C24XX: Documentation: update GPIO documentation
  ARM: S3C24XX: Documentation: update documentation overview
  ARM: SAMSUNG: Documentation: update directory layout
  ARM: SAMSUNG: Documentation: update the list of SoCs supported

204 files changed:
Documentation/filesystems/Locking
Documentation/filesystems/vfs.txt
Documentation/kernel-parameters.txt
arch/frv/include/asm/cache.h
arch/frv/include/asm/mem-layout.h
arch/powerpc/platforms/cell/spufs/file.c
arch/powerpc/platforms/cell/spufs/inode.c
drivers/ata/Kconfig
drivers/ata/Makefile
drivers/ata/ata_generic.c
drivers/ata/ata_piix.c
drivers/ata/libata-core.c
drivers/ata/libata-sff.c
drivers/ata/pata_acpi.c
drivers/ata/pata_ali.c
drivers/ata/pata_amd.c
drivers/ata/pata_artop.c
drivers/ata/pata_atiixp.c
drivers/ata/pata_atp867x.c
drivers/ata/pata_bf54x.c
drivers/ata/pata_cmd64x.c
drivers/ata/pata_cs5520.c
drivers/ata/pata_cs5530.c
drivers/ata/pata_cs5535.c
drivers/ata/pata_cs5536.c
drivers/ata/pata_cypress.c
drivers/ata/pata_efar.c
drivers/ata/pata_hpt366.c
drivers/ata/pata_hpt37x.c
drivers/ata/pata_hpt3x2n.c
drivers/ata/pata_hpt3x3.c
drivers/ata/pata_icside.c
drivers/ata/pata_it8213.c
drivers/ata/pata_it821x.c
drivers/ata/pata_jmicron.c
drivers/ata/pata_macio.c
drivers/ata/pata_marvell.c
drivers/ata/pata_mpc52xx.c
drivers/ata/pata_netcell.c
drivers/ata/pata_ninja32.c
drivers/ata/pata_ns87415.c
drivers/ata/pata_octeon_cf.c
drivers/ata/pata_oldpiix.c
drivers/ata/pata_optidma.c
drivers/ata/pata_pdc2027x.c
drivers/ata/pata_pdc202xx_old.c
drivers/ata/pata_piccolo.c
drivers/ata/pata_radisys.c
drivers/ata/pata_rdc.c
drivers/ata/pata_sc1200.c
drivers/ata/pata_scc.c
drivers/ata/pata_sch.c
drivers/ata/pata_serverworks.c
drivers/ata/pata_sil680.c
drivers/ata/pata_sis.c
drivers/ata/pata_sl82c105.c
drivers/ata/pata_triflex.c
drivers/ata/pata_via.c
drivers/ata/sata_mv.c
drivers/ata/sata_nv.c
drivers/ata/sata_qstor.c
drivers/ata/sata_sil.c
drivers/ata/sata_sis.c
drivers/ata/sata_svw.c
drivers/ata/sata_uli.c
drivers/ata/sata_via.c
drivers/ata/sata_vsc.c
drivers/char/ps3flash.c
drivers/mtd/ubi/cdev.c
drivers/net/3c507.c
drivers/net/benet/be_cmds.c
drivers/net/benet/be_main.c
drivers/net/cnic.c
drivers/net/cnic_if.h
drivers/net/fec.c
drivers/net/hamradio/yam.c
drivers/net/ll_temac.h
drivers/net/ll_temac_main.c
drivers/staging/pohmelfs/inode.c
drivers/usb/gadget/printer.c
drivers/vhost/net.c
drivers/vhost/vhost.c
drivers/video/fb_defio.c
fs/9p/vfs_file.c
fs/adfs/dir.c
fs/adfs/file.c
fs/adfs/inode.c
fs/affs/affs.h
fs/affs/file.c
fs/afs/internal.h
fs/afs/write.c
fs/aio.c
fs/anon_inodes.c
fs/attr.c
fs/bad_inode.c
fs/bfs/dir.c
fs/block_dev.c
fs/btrfs/ctree.h
fs/btrfs/file.c
fs/buffer.c
fs/ceph/caps.c
fs/ceph/dir.c
fs/ceph/super.h
fs/cifs/cifsfs.h
fs/cifs/file.c
fs/coda/coda_int.h
fs/coda/file.c
fs/configfs/inode.c
fs/direct-io.c
fs/ecryptfs/file.c
fs/ecryptfs/inode.c
fs/exofs/file.c
fs/ext2/ext2.h
fs/ext2/file.c
fs/ext2/inode.c
fs/ext3/fsync.c
fs/ext4/ext4.h
fs/ext4/fsync.c
fs/fat/fat.h
fs/fat/file.c
fs/fat/inode.c
fs/file_table.c
fs/fuse/dir.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/gfs2/aops.c
fs/gfs2/file.c
fs/gfs2/ops_inode.c
fs/hostfs/hostfs_kern.c
fs/hpfs/file.c
fs/hpfs/hpfs_fn.h
fs/hppfs/hppfs.c
fs/hugetlbfs/inode.c
fs/jffs2/file.c
fs/jffs2/fs.c
fs/jffs2/os-linux.h
fs/jfs/file.c
fs/jfs/jfs_inode.h
fs/libfs.c
fs/logfs/file.c
fs/logfs/logfs.h
fs/minix/dir.c
fs/minix/file.c
fs/minix/itree_v2.c
fs/namei.c
fs/ncpfs/file.c
fs/nfs/dir.c
fs/nfs/file.c
fs/nilfs2/file.c
fs/nilfs2/nilfs.h
fs/ntfs/dir.c
fs/ntfs/file.c
fs/ocfs2/file.c
fs/omfs/file.c
fs/pipe.c
fs/qnx4/dir.c
fs/ramfs/file-mmu.c
fs/ramfs/file-nommu.c
fs/reiserfs/dir.c
fs/reiserfs/file.c
fs/smbfs/file.c
fs/smbfs/inode.c
fs/super.c
fs/sync.c
fs/sysfs/inode.c
fs/sysv/dir.c
fs/sysv/file.c
fs/sysv/inode.c
fs/ubifs/file.c
fs/ubifs/ubifs.h
fs/udf/dir.c
fs/udf/file.c
fs/ufs/dir.c
fs/ufs/file.c
fs/ufs/truncate.c
fs/xfs/linux-2.6/xfs_file.c
include/linux/buffer_head.h
include/linux/ext3_fs.h
include/linux/fb.h
include/linux/file.h
include/linux/fs.h
include/linux/libata.h
include/net/cls_cgroup.h
include/net/sctp/structs.h
include/net/sock.h
include/trace/events/ext4.h
ipc/shm.c
kernel/hrtimer.c
kernel/perf_event.c
kernel/posix-timers.c
kernel/timer.c
mm/shmem.c
mm/truncate.c
net/core/datagram.c
net/core/neighbour.c
net/core/rtnetlink.c
net/core/sock.c
net/ipv4/ipmr.c
net/ipv4/udp.c
net/ipv6/ip6_output.c
net/ipv6/ip6mr.c
net/ipv6/udp.c
net/iucv/af_iucv.c
net/netfilter/xt_TEE.c

index 61c98f0..96d4293 100644 (file)
@@ -380,7 +380,7 @@ prototypes:
        int (*open) (struct inode *, struct file *);
        int (*flush) (struct file *);
        int (*release) (struct inode *, struct file *);
-       int (*fsync) (struct file *, struct dentry *, int datasync);
+       int (*fsync) (struct file *, int datasync);
        int (*aio_fsync) (struct kiocb *, int datasync);
        int (*fasync) (int, struct file *, int);
        int (*lock) (struct file *, int, struct file_lock *);
index b668585..94677e7 100644 (file)
@@ -401,11 +401,16 @@ otherwise noted.
        started might not be in the page cache at the end of the
        walk).
 
-  truncate: called by the VFS to change the size of a file.  The
+  truncate: Deprecated. This will not be called if ->setsize is defined.
+       Called by the VFS to change the size of a file.  The
        i_size field of the inode is set to the desired size by the
        VFS before this method is called.  This method is called by
        the truncate(2) system call and related functionality.
 
+       Note: ->truncate and vmtruncate are deprecated. Do not add new
+       instances/calls of these. Filesystems should be converted to do their
+       truncate sequence via ->setattr().
+
   permission: called by the VFS to check for access rights on a POSIX-like
        filesystem.
 
@@ -729,7 +734,7 @@ struct file_operations {
        int (*open) (struct inode *, struct file *);
        int (*flush) (struct file *);
        int (*release) (struct inode *, struct file *);
-       int (*fsync) (struct file *, struct dentry *, int datasync);
+       int (*fsync) (struct file *, int datasync);
        int (*aio_fsync) (struct kiocb *, int datasync);
        int (*fasync) (int, struct file *, int);
        int (*lock) (struct file *, int, struct file_lock *);
index b56ea86..a5c0550 100644 (file)
@@ -1252,6 +1252,8 @@ and is between 256 and 4096 characters. It is defined in the file
                        * nohrst, nosrst, norst: suppress hard, soft
                           and both resets.
 
+                       * dump_id: dump IDENTIFY data.
+
                        If there are multiple matching configurations changing
                        the same attribute, the last one is used.
 
index 7dc0f0f..2797163 100644 (file)
@@ -17,8 +17,6 @@
 #define L1_CACHE_SHIFT         (CONFIG_FRV_L1_CACHE_SHIFT)
 #define L1_CACHE_BYTES         (1 << L1_CACHE_SHIFT)
 
-#define ARCH_KMALLOC_MINALIGN  L1_CACHE_BYTES
-
 #define __cacheline_aligned    __attribute__((aligned(L1_CACHE_BYTES)))
 #define ____cacheline_aligned  __attribute__((aligned(L1_CACHE_BYTES)))
 
index 2947764..ccae981 100644 (file)
@@ -35,8 +35,8 @@
  * the slab must be aligned such that load- and store-double instructions don't
  * fault if used
  */
-#define        ARCH_KMALLOC_MINALIGN           8
-#define        ARCH_SLAB_MINALIGN              8
+#define        ARCH_KMALLOC_MINALIGN           L1_CACHE_BYTES
+#define        ARCH_SLAB_MINALIGN              L1_CACHE_BYTES
 
 /*****************************************************************************/
 /*
index 5c28082..1a40da9 100644 (file)
@@ -1849,8 +1849,7 @@ out:
        return ret;
 }
 
-static int spufs_mfc_fsync(struct file *file, struct dentry *dentry,
-                          int datasync)
+static int spufs_mfc_fsync(struct file *file, int datasync)
 {
        return spufs_mfc_flush(file, NULL);
 }
index fc1b1c4..e5e5f82 100644 (file)
@@ -251,7 +251,7 @@ const struct file_operations spufs_context_fops = {
        .llseek         = dcache_dir_lseek,
        .read           = generic_read_dir,
        .readdir        = dcache_readdir,
-       .fsync          = simple_sync_file,
+       .fsync          = noop_fsync,
 };
 EXPORT_SYMBOL_GPL(spufs_context_fops);
 
index e68541f..73f8833 100644 (file)
@@ -57,6 +57,8 @@ config SATA_PMP
          This option adds support for SATA Port Multipliers
          (the SATA version of an ethernet hub, or SAS expander).
 
+comment "Controllers with non-SFF native interface"
+
 config SATA_AHCI
        tristate "AHCI SATA support"
        depends on PCI
@@ -73,11 +75,12 @@ config SATA_AHCI_PLATFORM
 
          If unsure, say N.
 
-config SATA_SIL24
-       tristate "Silicon Image 3124/3132 SATA support"
-       depends on PCI
+config SATA_FSL
+       tristate "Freescale 3.0Gbps SATA support"
+       depends on FSL_SOC
        help
-         This option enables support for Silicon Image 3124/3132 Serial ATA.
+         This option enables support for Freescale 3.0Gbps SATA controller.
+         It can be found on MPC837x and MPC8315.
 
          If unsure, say N.
 
@@ -87,12 +90,11 @@ config SATA_INIC162X
        help
          This option enables support for Initio 162x Serial ATA.
 
-config SATA_FSL
-       tristate "Freescale 3.0Gbps SATA support"
-       depends on FSL_SOC
+config SATA_SIL24
+       tristate "Silicon Image 3124/3132 SATA support"
+       depends on PCI
        help
-         This option enables support for Freescale 3.0Gbps SATA controller.
-         It can be found on MPC837x and MPC8315.
+         This option enables support for Silicon Image 3124/3132 Serial ATA.
 
          If unsure, say N.
 
@@ -116,15 +118,65 @@ config ATA_SFF
 
 if ATA_SFF
 
-config SATA_SVW
-       tristate "ServerWorks Frodo / Apple K2 SATA support"
+comment "SFF controllers with custom DMA interface"
+
+config PDC_ADMA
+       tristate "Pacific Digital ADMA support"
        depends on PCI
        help
-         This option enables support for Broadcom/Serverworks/Apple K2
-         SATA support.
+         This option enables support for Pacific Digital ADMA controllers
+
+         If unsure, say N.
+
+config PATA_MPC52xx
+       tristate "Freescale MPC52xx SoC internal IDE"
+       depends on PPC_MPC52xx && PPC_BESTCOMM
+       select PPC_BESTCOMM_ATA
+       help
+         This option enables support for integrated IDE controller
+         of the Freescale MPC52xx SoC.
+
+         If unsure, say N.
+
+config PATA_OCTEON_CF
+       tristate "OCTEON Boot Bus Compact Flash support"
+       depends on CPU_CAVIUM_OCTEON
+       help
+         This option enables a polled compact flash driver for use with
+         compact flash cards attached to the OCTEON boot bus.
+
+         If unsure, say N.
+
+config SATA_QSTOR
+       tristate "Pacific Digital SATA QStor support"
+       depends on PCI
+       help
+         This option enables support for Pacific Digital Serial ATA QStor.
+
+         If unsure, say N.
+
+config SATA_SX4
+       tristate "Promise SATA SX4 support (Experimental)"
+       depends on PCI && EXPERIMENTAL
+       help
+         This option enables support for Promise Serial ATA SX4.
 
          If unsure, say N.
 
+config ATA_BMDMA
+       bool "ATA BMDMA support"
+       default y
+       help
+         This option adds support for SFF ATA controllers with BMDMA
+         capability.  BMDMA stands for bus-master DMA and the
+         de-facto DMA interface for SFF controllers.
+
+         If unuser, say Y.
+
+if ATA_BMDMA
+
+comment "SATA SFF controllers with BMDMA"
+
 config ATA_PIIX
        tristate "Intel ESB, ICH, PIIX3, PIIX4 PATA/SATA support"
        depends on PCI
@@ -152,22 +204,6 @@ config SATA_NV
 
          If unsure, say N.
 
-config PDC_ADMA
-       tristate "Pacific Digital ADMA support"
-       depends on PCI
-       help
-         This option enables support for Pacific Digital ADMA controllers
-
-         If unsure, say N.
-
-config SATA_QSTOR
-       tristate "Pacific Digital SATA QStor support"
-       depends on PCI
-       help
-         This option enables support for Pacific Digital Serial ATA QStor.
-
-         If unsure, say N.
-
 config SATA_PROMISE
        tristate "Promise SATA TX2/TX4 support"
        depends on PCI
@@ -176,14 +212,6 @@ config SATA_PROMISE
 
          If unsure, say N.
 
-config SATA_SX4
-       tristate "Promise SATA SX4 support (Experimental)"
-       depends on PCI && EXPERIMENTAL
-       help
-         This option enables support for Promise Serial ATA SX4.
-
-         If unsure, say N.
-
 config SATA_SIL
        tristate "Silicon Image SATA support"
        depends on PCI
@@ -203,6 +231,15 @@ config SATA_SIS
          enable the PATA_SIS driver in the config.
          If unsure, say N.
 
+config SATA_SVW
+       tristate "ServerWorks Frodo / Apple K2 SATA support"
+       depends on PCI
+       help
+         This option enables support for Broadcom/Serverworks/Apple K2
+         SATA support.
+
+         If unsure, say N.
+
 config SATA_ULI
        tristate "ULi Electronics SATA support"
        depends on PCI
@@ -227,14 +264,7 @@ config SATA_VITESSE
 
          If unsure, say N.
 
-config PATA_ACPI
-       tristate "ACPI firmware driver for PATA"
-       depends on ATA_ACPI
-       help
-         This option enables an ACPI method driver which drives
-         motherboard PATA controller interfaces through the ACPI
-         firmware in the BIOS. This driver can sometimes handle
-         otherwise unsupported hardware.
+comment "PATA SFF controllers with BMDMA"
 
 config PATA_ALI
        tristate "ALi PATA support"
@@ -262,40 +292,30 @@ config PATA_ARTOP
 
          If unsure, say N.
 
-config PATA_ATP867X
-       tristate "ARTOP/Acard ATP867X PATA support"
+config PATA_ATIIXP
+       tristate "ATI PATA support"
        depends on PCI
        help
-         This option enables support for ARTOP/Acard ATP867X PATA
-         controllers.
-
-         If unsure, say N.
-
-config PATA_AT32
-       tristate "Atmel AVR32 PATA support (Experimental)"
-       depends on AVR32 && PLATFORM_AT32AP && EXPERIMENTAL
-       help
-         This option enables support for the IDE devices on the
-         Atmel AT32AP platform.
+         This option enables support for the ATI ATA interfaces
+         found on the many ATI chipsets.
 
          If unsure, say N.
 
-config PATA_ATIIXP
-       tristate "ATI PATA support"
+config PATA_ATP867X
+       tristate "ARTOP/Acard ATP867X PATA support"
        depends on PCI
        help
-         This option enables support for the ATI ATA interfaces
-         found on the many ATI chipsets.
+         This option enables support for ARTOP/Acard ATP867X PATA
+         controllers.
 
          If unsure, say N.
 
-config PATA_CMD640_PCI
-       tristate "CMD640 PCI PATA support (Experimental)"
-       depends on PCI && EXPERIMENTAL
+config PATA_BF54X
+       tristate "Blackfin 54x ATAPI support"
+       depends on BF542 || BF548 || BF549
        help
-         This option enables support for the CMD640 PCI IDE
-         interface chip. Only the primary channel is currently
-         supported.
+         This option enables support for the built-in ATAPI controller on
+         Blackfin 54x family chips.
 
          If unsure, say N.
 
@@ -362,15 +382,6 @@ config PATA_EFAR
 
          If unsure, say N.
 
-config ATA_GENERIC
-       tristate "Generic ATA support"
-       depends on PCI
-       help
-         This option enables support for generic BIOS configured
-         ATA controllers via the new ATA layer
-
-         If unsure, say N.
-
 config PATA_HPT366
        tristate "HPT 366/368 PATA support"
        depends on PCI
@@ -415,12 +426,20 @@ config PATA_HPT3X3_DMA
          controllers. Enable with care as there are still some
          problems with DMA on this chipset.
 
-config PATA_ISAPNP
-       tristate "ISA Plug and Play PATA support"
-       depends on ISAPNP
+config PATA_ICSIDE
+       tristate "Acorn ICS PATA support"
+       depends on ARM && ARCH_ACORN
        help
-         This option enables support for ISA plug & play ATA
-         controllers such as those found on old soundcards.
+         On Acorn systems, say Y here if you wish to use the ICS PATA
+         interface card.  This is not required for ICS partition support.
+         If you are unsure, say N to this.
+
+config PATA_IT8213
+       tristate "IT8213 PATA support (Experimental)"
+       depends on PCI && EXPERIMENTAL
+       help
+         This option enables support for the ITE 821 PATA
+          controllers via the new ATA layer.
 
          If unsure, say N.
 
@@ -434,15 +453,6 @@ config PATA_IT821X
 
          If unsure, say N.
 
-config PATA_IT8213
-       tristate "IT8213 PATA support (Experimental)"
-       depends on PCI && EXPERIMENTAL
-       help
-         This option enables support for the ITE 821 PATA
-          controllers via the new ATA layer.
-
-         If unsure, say N.
-
 config PATA_JMICRON
        tristate "JMicron PATA support"
        depends on PCI
@@ -452,23 +462,14 @@ config PATA_JMICRON
 
          If unsure, say N.
 
-config PATA_LEGACY
-       tristate "Legacy ISA PATA support (Experimental)"
-       depends on (ISA || PCI)  && EXPERIMENTAL
-       help
-         This option enables support for ISA/VLB/PCI bus legacy PATA
-         ports and allows them to be accessed via the new ATA layer.
-
-         If unsure, say N.
-
-config PATA_TRIFLEX
-       tristate "Compaq Triflex PATA support"
-       depends on PCI
+config PATA_MACIO
+       tristate "Apple PowerMac/PowerBook internal 'MacIO' IDE"
+       depends on PPC_PMAC
        help
-         Enable support for the Compaq 'Triflex' IDE controller as found
-         on many Compaq Pentium-Pro systems, via the new ATA layer.
-
-         If unsure, say N.
+         Most IDE capable PowerMacs have IDE busses driven by a variant
+          of this controller which is part of the Apple chipset used on
+          most PowerMac models. Some models have multiple busses using
+          different chipsets, though generally, MacIO is one of them.
 
 config PATA_MARVELL
        tristate "Marvell PATA support via legacy mode"
@@ -481,32 +482,6 @@ config PATA_MARVELL
 
          If unsure, say N.
 
-config PATA_MPC52xx
-       tristate "Freescale MPC52xx SoC internal IDE"
-       depends on PPC_MPC52xx && PPC_BESTCOMM
-       select PPC_BESTCOMM_ATA
-       help
-         This option enables support for integrated IDE controller
-         of the Freescale MPC52xx SoC.
-
-         If unsure, say N.
-
-config PATA_MPIIX
-       tristate "Intel PATA MPIIX support"
-       depends on PCI
-       help
-         This option enables support for MPIIX PATA support.
-
-         If unsure, say N.
-
-config PATA_OLDPIIX
-       tristate "Intel PATA old PIIX support"
-       depends on PCI
-       help
-         This option enables support for early PIIX PATA support.
-
-         If unsure, say N.
-
 config PATA_NETCELL
        tristate "NETCELL Revolution RAID support"
        depends on PCI
@@ -525,15 +500,6 @@ config PATA_NINJA32
 
          If unsure, say N.
 
-config PATA_NS87410
-       tristate "Nat Semi NS87410 PATA support"
-       depends on PCI
-       help
-         This option enables support for the National Semiconductor
-         NS87410 PCI-IDE controller.
-
-         If unsure, say N.
-
 config PATA_NS87415
        tristate "Nat Semi NS87415 PATA support"
        depends on PCI
@@ -543,12 +509,11 @@ config PATA_NS87415
 
          If unsure, say N.
 
-config PATA_OPTI
-       tristate "OPTI621/6215 PATA support (Very Experimental)"
-       depends on PCI && EXPERIMENTAL
+config PATA_OLDPIIX
+       tristate "Intel PATA old PIIX support"
+       depends on PCI
        help
-         This option enables full PIO support for the early Opti ATA
-         controllers found on some old motherboards.
+         This option enables support for early PIIX PATA support.
 
          If unsure, say N.
 
@@ -562,24 +527,6 @@ config PATA_OPTIDMA
 
          If unsure, say N.
 
-config PATA_PALMLD
-       tristate "Palm LifeDrive PATA support"
-       depends on MACH_PALMLD
-       help
-         This option enables support for Palm LifeDrive's internal ATA
-         port via the new ATA layer.
-
-         If unsure, say N.
-
-config PATA_PCMCIA
-       tristate "PCMCIA PATA support"
-       depends on PCMCIA
-       help
-         This option enables support for PCMCIA ATA interfaces, including
-         compact flash card adapters via the new ATA layer.
-
-         If unsure, say N.
-
 config PATA_PDC2027X
        tristate "Promise PATA 2027x support"
        depends on PCI
@@ -597,12 +544,6 @@ config PATA_PDC_OLD
 
          If unsure, say N.
 
-config PATA_QDI
-       tristate "QDI VLB PATA support"
-       depends on ISA
-       help
-         Support for QDI 6500 and 6580 PATA controllers on VESA local bus.
-
 config PATA_RADISYS
        tristate "RADISYS 82600 PATA support (Experimental)"
        depends on PCI && EXPERIMENTAL
@@ -612,15 +553,6 @@ config PATA_RADISYS
 
          If unsure, say N.
 
-config PATA_RB532
-       tristate "RouterBoard 532 PATA CompactFlash support"
-       depends on MIKROTIK_RB532
-       help
-         This option enables support for the RouterBoard 532
-         PATA CompactFlash controller.
-
-         If unsure, say N.
-
 config PATA_RDC
        tristate "RDC PATA support"
        depends on PCI
@@ -631,21 +563,30 @@ config PATA_RDC
 
          If unsure, say N.
 
-config PATA_RZ1000
-       tristate "PC Tech RZ1000 PATA support"
+config PATA_SC1200
+       tristate "SC1200 PATA support"
        depends on PCI
        help
-         This option enables basic support for the PC Tech RZ1000/1
-         PATA controllers via the new ATA layer
+         This option enables support for the NatSemi/AMD SC1200 SoC
+         companion chip used with the Geode processor family.
 
          If unsure, say N.
 
-config PATA_SC1200
-       tristate "SC1200 PATA support"
+config PATA_SCC
+       tristate "Toshiba's Cell Reference Set IDE support"
+       depends on PCI && PPC_CELLEB
+       help
+         This option enables support for the built-in IDE controller on
+         Toshiba Cell Reference Board.
+
+         If unsure, say N.
+
+config PATA_SCH
+       tristate "Intel SCH PATA support"
        depends on PCI
        help
-         This option enables support for the NatSemi/AMD SC1200 SoC
-         companion chip used with the Geode processor family.
+         This option enables support for Intel SCH PATA on the Intel
+         SCH (US15W, US15L, UL11L) series host controllers.
 
          If unsure, say N.
 
@@ -683,6 +624,15 @@ config PATA_TOSHIBA
 
          If unsure, say N.
 
+config PATA_TRIFLEX
+       tristate "Compaq Triflex PATA support"
+       depends on PCI
+       help
+         Enable support for the Compaq 'Triflex' IDE controller as found
+         on many Compaq Pentium-Pro systems, via the new ATA layer.
+
+         If unsure, say N.
+
 config PATA_VIA
        tristate "VIA PATA support"
        depends on PCI
@@ -701,12 +651,99 @@ config PATA_WINBOND
 
          If unsure, say N.
 
-config PATA_WINBOND_VLB
-       tristate "Winbond W83759A VLB PATA support (Experimental)"
-       depends on ISA && EXPERIMENTAL
+endif # ATA_BMDMA
+
+comment "PIO-only SFF controllers"
+
+config PATA_AT32
+       tristate "Atmel AVR32 PATA support (Experimental)"
+       depends on AVR32 && PLATFORM_AT32AP && EXPERIMENTAL
        help
-         Support for the Winbond W83759A controller on Vesa Local Bus
-         systems.
+         This option enables support for the IDE devices on the
+         Atmel AT32AP platform.
+
+         If unsure, say N.
+
+config PATA_AT91
+       tristate "PATA support for AT91SAM9260"
+       depends on ARM && ARCH_AT91
+       help
+         This option enables support for IDE devices on the Atmel AT91SAM9260 SoC.
+
+         If unsure, say N.
+
+config PATA_CMD640_PCI
+       tristate "CMD640 PCI PATA support (Experimental)"
+       depends on PCI && EXPERIMENTAL
+       help
+         This option enables support for the CMD640 PCI IDE
+         interface chip. Only the primary channel is currently
+         supported.
+
+         If unsure, say N.
+
+config PATA_ISAPNP
+       tristate "ISA Plug and Play PATA support"
+       depends on ISAPNP
+       help
+         This option enables support for ISA plug & play ATA
+         controllers such as those found on old soundcards.
+
+         If unsure, say N.
+
+config PATA_IXP4XX_CF
+       tristate "IXP4XX Compact Flash support"
+       depends on ARCH_IXP4XX
+       help
+         This option enables support for a Compact Flash connected on
+         the ixp4xx expansion bus. This driver had been written for
+         Loft/Avila boards in mind but can work with others.
+
+         If unsure, say N.
+
+config PATA_MPIIX
+       tristate "Intel PATA MPIIX support"
+       depends on PCI
+       help
+         This option enables support for MPIIX PATA support.
+
+         If unsure, say N.
+
+config PATA_NS87410
+       tristate "Nat Semi NS87410 PATA support"
+       depends on PCI
+       help
+         This option enables support for the National Semiconductor
+         NS87410 PCI-IDE controller.
+
+         If unsure, say N.
+
+config PATA_OPTI
+       tristate "OPTI621/6215 PATA support (Very Experimental)"
+       depends on PCI && EXPERIMENTAL
+       help
+         This option enables full PIO support for the early Opti ATA
+         controllers found on some old motherboards.
+
+         If unsure, say N.
+
+config PATA_PALMLD
+       tristate "Palm LifeDrive PATA support"
+       depends on MACH_PALMLD
+       help
+         This option enables support for Palm LifeDrive's internal ATA
+         port via the new ATA layer.
+
+         If unsure, say N.
+
+config PATA_PCMCIA
+       tristate "PCMCIA PATA support"
+       depends on PCMCIA
+       help
+         This option enables support for PCMCIA ATA interfaces, including
+         compact flash card adapters via the new ATA layer.
+
+         If unsure, say N.
 
 config HAVE_PATA_PLATFORM
        bool
@@ -725,14 +762,6 @@ config PATA_PLATFORM
 
          If unsure, say N.
 
-config PATA_AT91
-       tristate "PATA support for AT91SAM9260"
-       depends on ARM && ARCH_AT91
-       help
-         This option enables support for IDE devices on the Atmel AT91SAM9260 SoC.
-
-         If unsure, say N.
-
 config PATA_OF_PLATFORM
        tristate "OpenFirmware platform device PATA support"
        depends on PATA_PLATFORM && PPC_OF
@@ -743,69 +772,65 @@ config PATA_OF_PLATFORM
 
          If unsure, say N.
 
-config PATA_ICSIDE
-       tristate "Acorn ICS PATA support"
-       depends on ARM && ARCH_ACORN
+config PATA_QDI
+       tristate "QDI VLB PATA support"
+       depends on ISA
        help
-         On Acorn systems, say Y here if you wish to use the ICS PATA
-         interface card.  This is not required for ICS partition support.
-         If you are unsure, say N to this.
+         Support for QDI 6500 and 6580 PATA controllers on VESA local bus.
 
-config PATA_IXP4XX_CF
-       tristate "IXP4XX Compact Flash support"
-       depends on ARCH_IXP4XX
+config PATA_RB532
+       tristate "RouterBoard 532 PATA CompactFlash support"
+       depends on MIKROTIK_RB532
        help
-         This option enables support for a Compact Flash connected on
-         the ixp4xx expansion bus. This driver had been written for
-         Loft/Avila boards in mind but can work with others.
+         This option enables support for the RouterBoard 532
+         PATA CompactFlash controller.
 
          If unsure, say N.
 
-config PATA_OCTEON_CF
-       tristate "OCTEON Boot Bus Compact Flash support"
-       depends on CPU_CAVIUM_OCTEON
+config PATA_RZ1000
+       tristate "PC Tech RZ1000 PATA support"
+       depends on PCI
        help
-         This option enables a polled compact flash driver for use with
-         compact flash cards attached to the OCTEON boot bus.
+         This option enables basic support for the PC Tech RZ1000/1
+         PATA controllers via the new ATA layer
 
          If unsure, say N.
 
-config PATA_SCC
-       tristate "Toshiba's Cell Reference Set IDE support"
-       depends on PCI && PPC_CELLEB
+config PATA_WINBOND_VLB
+       tristate "Winbond W83759A VLB PATA support (Experimental)"
+       depends on ISA && EXPERIMENTAL
        help
-         This option enables support for the built-in IDE controller on
-         Toshiba Cell Reference Board.
+         Support for the Winbond W83759A controller on Vesa Local Bus
+         systems.
 
-         If unsure, say N.
+comment "Generic fallback / legacy drivers"
 
-config PATA_SCH
-       tristate "Intel SCH PATA support"
-       depends on PCI
+config PATA_ACPI
+       tristate "ACPI firmware driver for PATA"
+       depends on ATA_ACPI && ATA_BMDMA
        help
-         This option enables support for Intel SCH PATA on the Intel
-         SCH (US15W, US15L, UL11L) series host controllers.
-
-         If unsure, say N.
+         This option enables an ACPI method driver which drives
+         motherboard PATA controller interfaces through the ACPI
+         firmware in the BIOS. This driver can sometimes handle
+         otherwise unsupported hardware.
 
-config PATA_BF54X
-       tristate "Blackfin 54x ATAPI support"
-       depends on BF542 || BF548 || BF549
+config ATA_GENERIC
+       tristate "Generic ATA support"
+       depends on PCI && ATA_BMDMA
        help
-         This option enables support for the built-in ATAPI controller on
-         Blackfin 54x family chips.
+         This option enables support for generic BIOS configured
+         ATA controllers via the new ATA layer
 
          If unsure, say N.
 
-config PATA_MACIO
-       tristate "Apple PowerMac/PowerBook internal 'MacIO' IDE"
-       depends on PPC_PMAC
+config PATA_LEGACY
+       tristate "Legacy ISA PATA support (Experimental)"
+       depends on (ISA || PCI) && EXPERIMENTAL
        help
-         Most IDE capable PowerMacs have IDE busses driven by a variant
-          of this controller which is part of the Apple chipset used on
-          most PowerMac models. Some models have multiple busses using
-          different chipsets, though generally, MacIO is one of them.
+         This option enables support for ISA/VLB/PCI bus legacy PATA
+         ports and allows them to be accessed via the new ATA layer.
 
+         If unsure, say N.
 
 endif # ATA_SFF
 endif # ATA
index d0a93c4..7ef89d7 100644 (file)
@@ -1,33 +1,39 @@
 
 obj-$(CONFIG_ATA)              += libata.o
 
+# non-SFF interface
 obj-$(CONFIG_SATA_AHCI)                += ahci.o libahci.o
 obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o
-obj-$(CONFIG_SATA_SVW)         += sata_svw.o
+obj-$(CONFIG_SATA_FSL)         += sata_fsl.o
+obj-$(CONFIG_SATA_INIC162X)    += sata_inic162x.o
+obj-$(CONFIG_SATA_SIL24)       += sata_sil24.o
+
+# SFF w/ custom DMA
+obj-$(CONFIG_PDC_ADMA)         += pdc_adma.o
+obj-$(CONFIG_PATA_MPC52xx)     += pata_mpc52xx.o
+obj-$(CONFIG_PATA_OCTEON_CF)   += pata_octeon_cf.o
+obj-$(CONFIG_SATA_QSTOR)       += sata_qstor.o
+obj-$(CONFIG_SATA_SX4)         += sata_sx4.o
+
+# SFF SATA w/ BMDMA
 obj-$(CONFIG_ATA_PIIX)         += ata_piix.o
+obj-$(CONFIG_SATA_MV)          += sata_mv.o
+obj-$(CONFIG_SATA_NV)          += sata_nv.o
 obj-$(CONFIG_SATA_PROMISE)     += sata_promise.o
-obj-$(CONFIG_SATA_QSTOR)       += sata_qstor.o
 obj-$(CONFIG_SATA_SIL)         += sata_sil.o
-obj-$(CONFIG_SATA_SIL24)       += sata_sil24.o
-obj-$(CONFIG_SATA_VIA)         += sata_via.o
-obj-$(CONFIG_SATA_VITESSE)     += sata_vsc.o
 obj-$(CONFIG_SATA_SIS)         += sata_sis.o
-obj-$(CONFIG_SATA_SX4)         += sata_sx4.o
-obj-$(CONFIG_SATA_NV)          += sata_nv.o
+obj-$(CONFIG_SATA_SVW)         += sata_svw.o
 obj-$(CONFIG_SATA_ULI)         += sata_uli.o
-obj-$(CONFIG_SATA_MV)          += sata_mv.o
-obj-$(CONFIG_SATA_INIC162X)    += sata_inic162x.o
-obj-$(CONFIG_PDC_ADMA)         += pdc_adma.o
-obj-$(CONFIG_SATA_FSL)         += sata_fsl.o
-obj-$(CONFIG_PATA_MACIO)       += pata_macio.o
+obj-$(CONFIG_SATA_VIA)         += sata_via.o
+obj-$(CONFIG_SATA_VITESSE)     += sata_vsc.o
 
+# SFF PATA w/ BMDMA
 obj-$(CONFIG_PATA_ALI)         += pata_ali.o
 obj-$(CONFIG_PATA_AMD)         += pata_amd.o
 obj-$(CONFIG_PATA_ARTOP)       += pata_artop.o
-obj-$(CONFIG_PATA_ATP867X)     += pata_atp867x.o
-obj-$(CONFIG_PATA_AT32)                += pata_at32.o
 obj-$(CONFIG_PATA_ATIIXP)      += pata_atiixp.o
-obj-$(CONFIG_PATA_CMD640_PCI)  += pata_cmd640.o
+obj-$(CONFIG_PATA_ATP867X)     += pata_atp867x.o
+obj-$(CONFIG_PATA_BF54X)       += pata_bf54x.o
 obj-$(CONFIG_PATA_CMD64X)      += pata_cmd64x.o
 obj-$(CONFIG_PATA_CS5520)      += pata_cs5520.o
 obj-$(CONFIG_PATA_CS5530)      += pata_cs5530.o
@@ -39,47 +45,50 @@ obj-$(CONFIG_PATA_HPT366)   += pata_hpt366.o
 obj-$(CONFIG_PATA_HPT37X)      += pata_hpt37x.o
 obj-$(CONFIG_PATA_HPT3X2N)     += pata_hpt3x2n.o
 obj-$(CONFIG_PATA_HPT3X3)      += pata_hpt3x3.o
-obj-$(CONFIG_PATA_ISAPNP)      += pata_isapnp.o
-obj-$(CONFIG_PATA_IT821X)      += pata_it821x.o
+obj-$(CONFIG_PATA_ICSIDE)      += pata_icside.o
 obj-$(CONFIG_PATA_IT8213)      += pata_it8213.o
+obj-$(CONFIG_PATA_IT821X)      += pata_it821x.o
 obj-$(CONFIG_PATA_JMICRON)     += pata_jmicron.o
+obj-$(CONFIG_PATA_MACIO)       += pata_macio.o
+obj-$(CONFIG_PATA_MARVELL)     += pata_marvell.o
 obj-$(CONFIG_PATA_NETCELL)     += pata_netcell.o
 obj-$(CONFIG_PATA_NINJA32)     += pata_ninja32.o
-obj-$(CONFIG_PATA_NS87410)     += pata_ns87410.o
 obj-$(CONFIG_PATA_NS87415)     += pata_ns87415.o
-obj-$(CONFIG_PATA_OPTI)                += pata_opti.o
-obj-$(CONFIG_PATA_OPTIDMA)     += pata_optidma.o
-obj-$(CONFIG_PATA_MPC52xx)     += pata_mpc52xx.o
-obj-$(CONFIG_PATA_MARVELL)     += pata_marvell.o
-obj-$(CONFIG_PATA_MPIIX)       += pata_mpiix.o
 obj-$(CONFIG_PATA_OLDPIIX)     += pata_oldpiix.o
-obj-$(CONFIG_PATA_PALMLD)      += pata_palmld.o
-obj-$(CONFIG_PATA_PCMCIA)      += pata_pcmcia.o
+obj-$(CONFIG_PATA_OPTIDMA)     += pata_optidma.o
 obj-$(CONFIG_PATA_PDC2027X)    += pata_pdc2027x.o
 obj-$(CONFIG_PATA_PDC_OLD)     += pata_pdc202xx_old.o
-obj-$(CONFIG_PATA_QDI)         += pata_qdi.o
 obj-$(CONFIG_PATA_RADISYS)     += pata_radisys.o
-obj-$(CONFIG_PATA_RB532)       += pata_rb532_cf.o
 obj-$(CONFIG_PATA_RDC)         += pata_rdc.o
-obj-$(CONFIG_PATA_RZ1000)      += pata_rz1000.o
 obj-$(CONFIG_PATA_SC1200)      += pata_sc1200.o
+obj-$(CONFIG_PATA_SCC)         += pata_scc.o
+obj-$(CONFIG_PATA_SCH)         += pata_sch.o
 obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o
 obj-$(CONFIG_PATA_SIL680)      += pata_sil680.o
+obj-$(CONFIG_PATA_SIS)         += pata_sis.o
 obj-$(CONFIG_PATA_TOSHIBA)     += pata_piccolo.o
+obj-$(CONFIG_PATA_TRIFLEX)     += pata_triflex.o
 obj-$(CONFIG_PATA_VIA)         += pata_via.o
 obj-$(CONFIG_PATA_WINBOND)     += pata_sl82c105.o
-obj-$(CONFIG_PATA_WINBOND_VLB) += pata_winbond.o
-obj-$(CONFIG_PATA_SIS)         += pata_sis.o
-obj-$(CONFIG_PATA_TRIFLEX)     += pata_triflex.o
+
+# SFF PIO only
+obj-$(CONFIG_PATA_AT32)                += pata_at32.o
+obj-$(CONFIG_PATA_AT91)                += pata_at91.o
+obj-$(CONFIG_PATA_CMD640_PCI)  += pata_cmd640.o
+obj-$(CONFIG_PATA_ISAPNP)      += pata_isapnp.o
 obj-$(CONFIG_PATA_IXP4XX_CF)   += pata_ixp4xx_cf.o
-obj-$(CONFIG_PATA_SCC)         += pata_scc.o
-obj-$(CONFIG_PATA_SCH)         += pata_sch.o
-obj-$(CONFIG_PATA_BF54X)       += pata_bf54x.o
-obj-$(CONFIG_PATA_OCTEON_CF)   += pata_octeon_cf.o
+obj-$(CONFIG_PATA_MPIIX)       += pata_mpiix.o
+obj-$(CONFIG_PATA_NS87410)     += pata_ns87410.o
+obj-$(CONFIG_PATA_OPTI)                += pata_opti.o
+obj-$(CONFIG_PATA_PCMCIA)      += pata_pcmcia.o
+obj-$(CONFIG_PATA_PALMLD)      += pata_palmld.o
 obj-$(CONFIG_PATA_PLATFORM)    += pata_platform.o
-obj-$(CONFIG_PATA_AT91)        += pata_at91.o
 obj-$(CONFIG_PATA_OF_PLATFORM) += pata_of_platform.o
-obj-$(CONFIG_PATA_ICSIDE)      += pata_icside.o
+obj-$(CONFIG_PATA_QDI)         += pata_qdi.o
+obj-$(CONFIG_PATA_RB532)       += pata_rb532_cf.o
+obj-$(CONFIG_PATA_RZ1000)      += pata_rz1000.o
+obj-$(CONFIG_PATA_WINBOND_VLB) += pata_winbond.o
+
 # Should be last but two libata driver
 obj-$(CONFIG_PATA_ACPI)                += pata_acpi.o
 # Should be last but one libata driver
index 33fb614..573158a 100644 (file)
@@ -155,7 +155,7 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
                        return rc;
                pcim_pin_device(dev);
        }
-       return ata_pci_sff_init_one(dev, ppi, &generic_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(dev, ppi, &generic_sht, NULL, 0);
 }
 
 static struct pci_device_id ata_generic[] = {
index ec52fc6..7409f98 100644 (file)
@@ -1589,7 +1589,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
                hpriv->map = piix_init_sata_map(pdev, port_info,
                                        piix_map_db_table[ent->driver_data]);
 
-       rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+       rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
        if (rc)
                return rc;
        host->private_data = hpriv;
@@ -1626,7 +1626,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
        host->flags |= ATA_HOST_PARALLEL_SCAN;
 
        pci_set_master(pdev);
-       return ata_pci_sff_activate_host(host, ata_sff_interrupt, &piix_sht);
+       return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, &piix_sht);
 }
 
 static void piix_remove_one(struct pci_dev *pdev)
index c47373f..06b7e49 100644 (file)
@@ -160,6 +160,10 @@ int libata_allow_tpm = 0;
 module_param_named(allow_tpm, libata_allow_tpm, int, 0444);
 MODULE_PARM_DESC(allow_tpm, "Permit the use of TPM commands (0=off [default], 1=on)");
 
+static int atapi_an;
+module_param(atapi_an, int, 0444);
+MODULE_PARM_DESC(atapi_an, "Enable ATAPI AN media presence notification (0=0ff [default], 1=on)");
+
 MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("Library module for ATA devices");
 MODULE_LICENSE("GPL");
@@ -2122,6 +2126,14 @@ retry:
                goto err_out;
        }
 
+       if (dev->horkage & ATA_HORKAGE_DUMP_ID) {
+               ata_dev_printk(dev, KERN_DEBUG, "dumping IDENTIFY data, "
+                              "class=%d may_fallback=%d tried_spinup=%d\n",
+                              class, may_fallback, tried_spinup);
+               print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET,
+                              16, 2, id, ATA_ID_WORDS * sizeof(*id), true);
+       }
+
        /* Falling back doesn't make sense if ID data was read
         * successfully at least once.
         */
@@ -2510,7 +2522,8 @@ int ata_dev_configure(struct ata_device *dev)
                 * to enable ATAPI AN to discern between PHY status
                 * changed notifications and ATAPI ANs.
                 */
-               if ((ap->flags & ATA_FLAG_AN) && ata_id_has_atapi_AN(id) &&
+               if (atapi_an &&
+                   (ap->flags & ATA_FLAG_AN) && ata_id_has_atapi_AN(id) &&
                    (!sata_pmp_attached(ap) ||
                     sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf) == 0)) {
                        unsigned int err_mask;
@@ -6372,6 +6385,7 @@ static int __init ata_parse_force_one(char **cur,
                { "3.0Gbps",    .spd_limit      = 2 },
                { "noncq",      .horkage_on     = ATA_HORKAGE_NONCQ },
                { "ncq",        .horkage_off    = ATA_HORKAGE_NONCQ },
+               { "dump_id",    .horkage_on     = ATA_HORKAGE_DUMP_ID },
                { "pio0",       .xfer_mask      = 1 << (ATA_SHIFT_PIO + 0) },
                { "pio1",       .xfer_mask      = 1 << (ATA_SHIFT_PIO + 1) },
                { "pio2",       .xfer_mask      = 1 << (ATA_SHIFT_PIO + 2) },
index 19ddf92..efa4a18 100644 (file)
@@ -63,7 +63,6 @@ const struct ata_port_operations ata_sff_port_ops = {
        .sff_tf_read            = ata_sff_tf_read,
        .sff_exec_command       = ata_sff_exec_command,
        .sff_data_xfer          = ata_sff_data_xfer,
-       .sff_irq_clear          = ata_sff_irq_clear,
        .sff_drain_fifo         = ata_sff_drain_fifo,
 
        .lost_interrupt         = ata_sff_lost_interrupt,
@@ -395,32 +394,11 @@ void ata_sff_irq_on(struct ata_port *ap)
                ata_sff_set_devctl(ap, ap->ctl);
        ata_wait_idle(ap);
 
-       ap->ops->sff_irq_clear(ap);
+       if (ap->ops->sff_irq_clear)
+               ap->ops->sff_irq_clear(ap);
 }
 EXPORT_SYMBOL_GPL(ata_sff_irq_on);
 
-/**
- *     ata_sff_irq_clear - Clear PCI IDE BMDMA interrupt.
- *     @ap: Port associated with this ATA transaction.
- *
- *     Clear interrupt and error flags in DMA status register.
- *
- *     May be used as the irq_clear() entry in ata_port_operations.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host lock)
- */
-void ata_sff_irq_clear(struct ata_port *ap)
-{
-       void __iomem *mmio = ap->ioaddr.bmdma_addr;
-
-       if (!mmio)
-               return;
-
-       iowrite8(ioread8(mmio + ATA_DMA_STATUS), mmio + ATA_DMA_STATUS);
-}
-EXPORT_SYMBOL_GPL(ata_sff_irq_clear);
-
 /**
  *     ata_sff_tf_load - send taskfile registers to host controller
  *     @ap: Port to which output is sent
@@ -820,11 +798,15 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
        case ATAPI_PROT_NODATA:
                ap->hsm_task_state = HSM_ST_LAST;
                break;
+#ifdef CONFIG_ATA_BMDMA
        case ATAPI_PROT_DMA:
                ap->hsm_task_state = HSM_ST_LAST;
                /* initiate bmdma */
                ap->ops->bmdma_start(qc);
                break;
+#endif /* CONFIG_ATA_BMDMA */
+       default:
+               BUG();
        }
 }
 
@@ -1491,27 +1473,27 @@ bool ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc)
 }
 EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf);
 
-/**
- *     ata_sff_host_intr - Handle host interrupt for given (port, task)
- *     @ap: Port on which interrupt arrived (possibly...)
- *     @qc: Taskfile currently active in engine
- *
- *     Handle host interrupt for given queued command.  Currently,
- *     only DMA interrupts are handled.  All other commands are
- *     handled via polling with interrupts disabled (nIEN bit).
- *
- *     LOCKING:
- *     spin_lock_irqsave(host lock)
- *
- *     RETURNS:
- *     One if interrupt was handled, zero if not (shared irq).
- */
-unsigned int ata_sff_host_intr(struct ata_port *ap,
-                                     struct ata_queued_cmd *qc)
+static unsigned int ata_sff_idle_irq(struct ata_port *ap)
 {
-       struct ata_eh_info *ehi = &ap->link.eh_info;
-       u8 status, host_stat = 0;
-       bool bmdma_stopped = false;
+       ap->stats.idle_irq++;
+
+#ifdef ATA_IRQ_TRAP
+       if ((ap->stats.idle_irq % 1000) == 0) {
+               ap->ops->sff_check_status(ap);
+               if (ap->ops->sff_irq_clear)
+                       ap->ops->sff_irq_clear(ap);
+               ata_port_printk(ap, KERN_WARNING, "irq trap\n");
+               return 1;
+       }
+#endif
+       return 0;       /* irq not handled */
+}
+
+static unsigned int __ata_sff_port_intr(struct ata_port *ap,
+                                       struct ata_queued_cmd *qc,
+                                       bool hsmv_on_idle)
+{
+       u8 status;
 
        VPRINTK("ata%u: protocol %d task_state %d\n",
                ap->print_id, qc->tf.protocol, ap->hsm_task_state);
@@ -1528,90 +1510,56 @@ unsigned int ata_sff_host_intr(struct ata_port *ap,
                 * need to check ata_is_atapi(qc->tf.protocol) again.
                 */
                if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
-                       goto idle_irq;
-               break;
-       case HSM_ST_LAST:
-               if (qc->tf.protocol == ATA_PROT_DMA ||
-                   qc->tf.protocol == ATAPI_PROT_DMA) {
-                       /* check status of DMA engine */
-                       host_stat = ap->ops->bmdma_status(ap);
-                       VPRINTK("ata%u: host_stat 0x%X\n",
-                               ap->print_id, host_stat);
-
-                       /* if it's not our irq... */
-                       if (!(host_stat & ATA_DMA_INTR))
-                               goto idle_irq;
-
-                       /* before we do anything else, clear DMA-Start bit */
-                       ap->ops->bmdma_stop(qc);
-                       bmdma_stopped = true;
-
-                       if (unlikely(host_stat & ATA_DMA_ERR)) {
-                               /* error when transfering data to/from memory */
-                               qc->err_mask |= AC_ERR_HOST_BUS;
-                               ap->hsm_task_state = HSM_ST_ERR;
-                       }
-               }
+                       return ata_sff_idle_irq(ap);
                break;
        case HSM_ST:
+       case HSM_ST_LAST:
                break;
        default:
-               goto idle_irq;
+               return ata_sff_idle_irq(ap);
        }
 
-
        /* check main status, clearing INTRQ if needed */
        status = ata_sff_irq_status(ap);
        if (status & ATA_BUSY) {
-               if (bmdma_stopped) {
+               if (hsmv_on_idle) {
                        /* BMDMA engine is already stopped, we're screwed */
                        qc->err_mask |= AC_ERR_HSM;
                        ap->hsm_task_state = HSM_ST_ERR;
                } else
-                       goto idle_irq;
+                       return ata_sff_idle_irq(ap);
        }
 
        /* clear irq events */
-       ap->ops->sff_irq_clear(ap);
+       if (ap->ops->sff_irq_clear)
+               ap->ops->sff_irq_clear(ap);
 
        ata_sff_hsm_move(ap, qc, status, 0);
 
-       if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
-                                      qc->tf.protocol == ATAPI_PROT_DMA))
-               ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
-
        return 1;       /* irq handled */
-
-idle_irq:
-       ap->stats.idle_irq++;
-
-#ifdef ATA_IRQ_TRAP
-       if ((ap->stats.idle_irq % 1000) == 0) {
-               ap->ops->sff_check_status(ap);
-               ap->ops->sff_irq_clear(ap);
-               ata_port_printk(ap, KERN_WARNING, "irq trap\n");
-               return 1;
-       }
-#endif
-       return 0;       /* irq not handled */
 }
-EXPORT_SYMBOL_GPL(ata_sff_host_intr);
 
 /**
- *     ata_sff_interrupt - Default ATA host interrupt handler
- *     @irq: irq line (unused)
- *     @dev_instance: pointer to our ata_host information structure
+ *     ata_sff_port_intr - Handle SFF port interrupt
+ *     @ap: Port on which interrupt arrived (possibly...)
+ *     @qc: Taskfile currently active in engine
  *
- *     Default interrupt handler for PCI IDE devices.  Calls
- *     ata_sff_host_intr() for each port that is not disabled.
+ *     Handle port interrupt for given queued command.
  *
  *     LOCKING:
- *     Obtains host lock during operation.
+ *     spin_lock_irqsave(host lock)
  *
  *     RETURNS:
- *     IRQ_NONE or IRQ_HANDLED.
+ *     One if interrupt was handled, zero if not (shared irq).
  */
-irqreturn_t ata_sff_interrupt(int irq, void *dev_instance)
+unsigned int ata_sff_port_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
+{
+       return __ata_sff_port_intr(ap, qc, false);
+}
+EXPORT_SYMBOL_GPL(ata_sff_port_intr);
+
+static inline irqreturn_t __ata_sff_interrupt(int irq, void *dev_instance,
+       unsigned int (*port_intr)(struct ata_port *, struct ata_queued_cmd *))
 {
        struct ata_host *host = dev_instance;
        bool retried = false;
@@ -1631,7 +1579,7 @@ retry:
                qc = ata_qc_from_tag(ap, ap->link.active_tag);
                if (qc) {
                        if (!(qc->tf.flags & ATA_TFLAG_POLLING))
-                               handled |= ata_sff_host_intr(ap, qc);
+                               handled |= port_intr(ap, qc);
                        else
                                polling |= 1 << i;
                } else
@@ -1658,7 +1606,8 @@ retry:
 
                        if (idle & (1 << i)) {
                                ap->ops->sff_check_status(ap);
-                               ap->ops->sff_irq_clear(ap);
+                               if (ap->ops->sff_irq_clear)
+                                       ap->ops->sff_irq_clear(ap);
                        } else {
                                /* clear INTRQ and check if BUSY cleared */
                                if (!(ap->ops->sff_check_status(ap) & ATA_BUSY))
@@ -1680,6 +1629,25 @@ retry:
 
        return IRQ_RETVAL(handled);
 }
+
+/**
+ *     ata_sff_interrupt - Default SFF ATA host interrupt handler
+ *     @irq: irq line (unused)
+ *     @dev_instance: pointer to our ata_host information structure
+ *
+ *     Default interrupt handler for PCI IDE devices.  Calls
+ *     ata_sff_port_intr() for each port that is not disabled.
+ *
+ *     LOCKING:
+ *     Obtains host lock during operation.
+ *
+ *     RETURNS:
+ *     IRQ_NONE or IRQ_HANDLED.
+ */
+irqreturn_t ata_sff_interrupt(int irq, void *dev_instance)
+{
+       return __ata_sff_interrupt(irq, dev_instance, ata_sff_port_intr);
+}
 EXPORT_SYMBOL_GPL(ata_sff_interrupt);
 
 /**
@@ -1717,7 +1685,7 @@ void ata_sff_lost_interrupt(struct ata_port *ap)
                                                                status);
        /* Run the host interrupt logic as if the interrupt had not been
           lost */
-       ata_sff_host_intr(ap, qc);
+       ata_sff_port_intr(ap, qc);
 }
 EXPORT_SYMBOL_GPL(ata_sff_lost_interrupt);
 
@@ -1744,7 +1712,8 @@ void ata_sff_freeze(struct ata_port *ap)
         */
        ap->ops->sff_check_status(ap);
 
-       ap->ops->sff_irq_clear(ap);
+       if (ap->ops->sff_irq_clear)
+               ap->ops->sff_irq_clear(ap);
 }
 EXPORT_SYMBOL_GPL(ata_sff_freeze);
 
@@ -1761,7 +1730,8 @@ void ata_sff_thaw(struct ata_port *ap)
 {
        /* clear & re-enable interrupts */
        ap->ops->sff_check_status(ap);
-       ap->ops->sff_irq_clear(ap);
+       if (ap->ops->sff_irq_clear)
+               ap->ops->sff_irq_clear(ap);
        ata_sff_irq_on(ap);
 }
 EXPORT_SYMBOL_GPL(ata_sff_thaw);
@@ -2349,13 +2319,13 @@ int ata_pci_sff_init_host(struct ata_host *host)
 EXPORT_SYMBOL_GPL(ata_pci_sff_init_host);
 
 /**
- *     ata_pci_sff_prepare_host - helper to prepare native PCI ATA host
+ *     ata_pci_sff_prepare_host - helper to prepare PCI PIO-only SFF ATA host
  *     @pdev: target PCI device
  *     @ppi: array of port_info, must be enough for two ports
  *     @r_host: out argument for the initialized ATA host
  *
- *     Helper to allocate ATA host for @pdev, acquire all native PCI
- *     resources and initialize it accordingly in one go.
+ *     Helper to allocate PIO-only SFF ATA host for @pdev, acquire
+ *     all PCI resources and initialize it accordingly in one go.
  *
  *     LOCKING:
  *     Inherited from calling layer (may sleep).
@@ -2385,9 +2355,6 @@ int ata_pci_sff_prepare_host(struct pci_dev *pdev,
        if (rc)
                goto err_out;
 
-       /* init DMA related stuff */
-       ata_pci_bmdma_init(host);
-
        devres_remove_group(&pdev->dev, NULL);
        *r_host = host;
        return 0;
@@ -2492,8 +2459,21 @@ out:
 }
 EXPORT_SYMBOL_GPL(ata_pci_sff_activate_host);
 
+static const struct ata_port_info *ata_sff_find_valid_pi(
+                                       const struct ata_port_info * const *ppi)
+{
+       int i;
+
+       /* look up the first valid port_info */
+       for (i = 0; i < 2 && ppi[i]; i++)
+               if (ppi[i]->port_ops != &ata_dummy_port_ops)
+                       return ppi[i];
+
+       return NULL;
+}
+
 /**
- *     ata_pci_sff_init_one - Initialize/register PCI IDE host controller
+ *     ata_pci_sff_init_one - Initialize/register PIO-only PCI IDE controller
  *     @pdev: Controller to be initialized
  *     @ppi: array of port_info, must be enough for two ports
  *     @sht: scsi_host_template to use when registering the host
@@ -2502,11 +2482,7 @@ EXPORT_SYMBOL_GPL(ata_pci_sff_activate_host);
  *
  *     This is a helper function which can be called from a driver's
  *     xxx_init_one() probe function if the hardware uses traditional
- *     IDE taskfile registers.
- *
- *     This function calls pci_enable_device(), reserves its register
- *     regions, sets the dma mask, enables bus master mode, and calls
- *     ata_device_add()
+ *     IDE taskfile registers and is PIO only.
  *
  *     ASSUMPTION:
  *     Nobody makes a single channel controller that appears solely as
@@ -2523,20 +2499,13 @@ int ata_pci_sff_init_one(struct pci_dev *pdev,
                 struct scsi_host_template *sht, void *host_priv, int hflag)
 {
        struct device *dev = &pdev->dev;
-       const struct ata_port_info *pi = NULL;
+       const struct ata_port_info *pi;
        struct ata_host *host = NULL;
-       int i, rc;
+       int rc;
 
        DPRINTK("ENTER\n");
 
-       /* look up the first valid port_info */
-       for (i = 0; i < 2 && ppi[i]; i++) {
-               if (ppi[i]->port_ops != &ata_dummy_port_ops) {
-                       pi = ppi[i];
-                       break;
-               }
-       }
-
+       pi = ata_sff_find_valid_pi(ppi);
        if (!pi) {
                dev_printk(KERN_ERR, &pdev->dev,
                           "no valid port_info specified\n");
@@ -2557,7 +2526,6 @@ int ata_pci_sff_init_one(struct pci_dev *pdev,
        host->private_data = host_priv;
        host->flags |= hflag;
 
-       pci_set_master(pdev);
        rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht);
 out:
        if (rc == 0)
@@ -2571,6 +2539,12 @@ EXPORT_SYMBOL_GPL(ata_pci_sff_init_one);
 
 #endif /* CONFIG_PCI */
 
+/*
+ *     BMDMA support
+ */
+
+#ifdef CONFIG_ATA_BMDMA
+
 const struct ata_port_operations ata_bmdma_port_ops = {
        .inherits               = &ata_sff_port_ops,
 
@@ -2580,6 +2554,7 @@ const struct ata_port_operations ata_bmdma_port_ops = {
        .qc_prep                = ata_bmdma_qc_prep,
        .qc_issue               = ata_bmdma_qc_issue,
 
+       .sff_irq_clear          = ata_bmdma_irq_clear,
        .bmdma_setup            = ata_bmdma_setup,
        .bmdma_start            = ata_bmdma_start,
        .bmdma_stop             = ata_bmdma_stop,
@@ -2803,6 +2778,75 @@ unsigned int ata_bmdma_qc_issue(struct ata_queued_cmd *qc)
 }
 EXPORT_SYMBOL_GPL(ata_bmdma_qc_issue);
 
+/**
+ *     ata_bmdma_port_intr - Handle BMDMA port interrupt
+ *     @ap: Port on which interrupt arrived (possibly...)
+ *     @qc: Taskfile currently active in engine
+ *
+ *     Handle port interrupt for given queued command.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host lock)
+ *
+ *     RETURNS:
+ *     One if interrupt was handled, zero if not (shared irq).
+ */
+unsigned int ata_bmdma_port_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
+{
+       struct ata_eh_info *ehi = &ap->link.eh_info;
+       u8 host_stat = 0;
+       bool bmdma_stopped = false;
+       unsigned int handled;
+
+       if (ap->hsm_task_state == HSM_ST_LAST && ata_is_dma(qc->tf.protocol)) {
+               /* check status of DMA engine */
+               host_stat = ap->ops->bmdma_status(ap);
+               VPRINTK("ata%u: host_stat 0x%X\n", ap->print_id, host_stat);
+
+               /* if it's not our irq... */
+               if (!(host_stat & ATA_DMA_INTR))
+                       return ata_sff_idle_irq(ap);
+
+               /* before we do anything else, clear DMA-Start bit */
+               ap->ops->bmdma_stop(qc);
+               bmdma_stopped = true;
+
+               if (unlikely(host_stat & ATA_DMA_ERR)) {
+                       /* error when transfering data to/from memory */
+                       qc->err_mask |= AC_ERR_HOST_BUS;
+                       ap->hsm_task_state = HSM_ST_ERR;
+               }
+       }
+
+       handled = __ata_sff_port_intr(ap, qc, bmdma_stopped);
+
+       if (unlikely(qc->err_mask) && ata_is_dma(qc->tf.protocol))
+               ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
+
+       return handled;
+}
+EXPORT_SYMBOL_GPL(ata_bmdma_port_intr);
+
+/**
+ *     ata_bmdma_interrupt - Default BMDMA ATA host interrupt handler
+ *     @irq: irq line (unused)
+ *     @dev_instance: pointer to our ata_host information structure
+ *
+ *     Default interrupt handler for PCI IDE devices.  Calls
+ *     ata_bmdma_port_intr() for each port that is not disabled.
+ *
+ *     LOCKING:
+ *     Obtains host lock during operation.
+ *
+ *     RETURNS:
+ *     IRQ_NONE or IRQ_HANDLED.
+ */
+irqreturn_t ata_bmdma_interrupt(int irq, void *dev_instance)
+{
+       return __ata_sff_interrupt(irq, dev_instance, ata_bmdma_port_intr);
+}
+EXPORT_SYMBOL_GPL(ata_bmdma_interrupt);
+
 /**
  *     ata_bmdma_error_handler - Stock error handler for BMDMA controller
  *     @ap: port to handle error for
@@ -2848,7 +2892,8 @@ void ata_bmdma_error_handler(struct ata_port *ap)
                /* if we're gonna thaw, make sure IRQ is clear */
                if (thaw) {
                        ap->ops->sff_check_status(ap);
-                       ap->ops->sff_irq_clear(ap);
+                       if (ap->ops->sff_irq_clear)
+                               ap->ops->sff_irq_clear(ap);
                }
        }
 
@@ -2881,6 +2926,28 @@ void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
 }
 EXPORT_SYMBOL_GPL(ata_bmdma_post_internal_cmd);
 
+/**
+ *     ata_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt.
+ *     @ap: Port associated with this ATA transaction.
+ *
+ *     Clear interrupt and error flags in DMA status register.
+ *
+ *     May be used as the irq_clear() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host lock)
+ */
+void ata_bmdma_irq_clear(struct ata_port *ap)
+{
+       void __iomem *mmio = ap->ioaddr.bmdma_addr;
+
+       if (!mmio)
+               return;
+
+       iowrite8(ioread8(mmio + ATA_DMA_STATUS), mmio + ATA_DMA_STATUS);
+}
+EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear);
+
 /**
  *     ata_bmdma_setup - Set up PCI IDE BMDMA transaction
  *     @qc: Info associated with this ATA transaction.
@@ -3137,7 +3204,100 @@ void ata_pci_bmdma_init(struct ata_host *host)
 }
 EXPORT_SYMBOL_GPL(ata_pci_bmdma_init);
 
+/**
+ *     ata_pci_bmdma_prepare_host - helper to prepare PCI BMDMA ATA host
+ *     @pdev: target PCI device
+ *     @ppi: array of port_info, must be enough for two ports
+ *     @r_host: out argument for the initialized ATA host
+ *
+ *     Helper to allocate BMDMA ATA host for @pdev, acquire all PCI
+ *     resources and initialize it accordingly in one go.
+ *
+ *     LOCKING:
+ *     Inherited from calling layer (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise.
+ */
+int ata_pci_bmdma_prepare_host(struct pci_dev *pdev,
+                              const struct ata_port_info * const * ppi,
+                              struct ata_host **r_host)
+{
+       int rc;
+
+       rc = ata_pci_sff_prepare_host(pdev, ppi, r_host);
+       if (rc)
+               return rc;
+
+       ata_pci_bmdma_init(*r_host);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ata_pci_bmdma_prepare_host);
+
+/**
+ *     ata_pci_bmdma_init_one - Initialize/register BMDMA PCI IDE controller
+ *     @pdev: Controller to be initialized
+ *     @ppi: array of port_info, must be enough for two ports
+ *     @sht: scsi_host_template to use when registering the host
+ *     @host_priv: host private_data
+ *     @hflags: host flags
+ *
+ *     This function is similar to ata_pci_sff_init_one() but also
+ *     takes care of BMDMA initialization.
+ *
+ *     LOCKING:
+ *     Inherited from PCI layer (may sleep).
+ *
+ *     RETURNS:
+ *     Zero on success, negative on errno-based value on error.
+ */
+int ata_pci_bmdma_init_one(struct pci_dev *pdev,
+                          const struct ata_port_info * const * ppi,
+                          struct scsi_host_template *sht, void *host_priv,
+                          int hflags)
+{
+       struct device *dev = &pdev->dev;
+       const struct ata_port_info *pi;
+       struct ata_host *host = NULL;
+       int rc;
+
+       DPRINTK("ENTER\n");
+
+       pi = ata_sff_find_valid_pi(ppi);
+       if (!pi) {
+               dev_printk(KERN_ERR, &pdev->dev,
+                          "no valid port_info specified\n");
+               return -EINVAL;
+       }
+
+       if (!devres_open_group(dev, NULL, GFP_KERNEL))
+               return -ENOMEM;
+
+       rc = pcim_enable_device(pdev);
+       if (rc)
+               goto out;
+
+       /* prepare and activate BMDMA host */
+       rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
+       if (rc)
+               goto out;
+       host->private_data = host_priv;
+       host->flags |= hflags;
+
+       pci_set_master(pdev);
+       rc = ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht);
+ out:
+       if (rc == 0)
+               devres_remove_group(&pdev->dev, NULL);
+       else
+               devres_release_group(&pdev->dev, NULL);
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(ata_pci_bmdma_init_one);
+
 #endif /* CONFIG_PCI */
+#endif /* CONFIG_ATA_BMDMA */
 
 /**
  *     ata_sff_port_init - Initialize SFF/BMDMA ATA port
index 066b9f3..c8d4703 100644 (file)
@@ -260,7 +260,7 @@ static int pacpi_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
                        return rc;
                pcim_pin_device(pdev);
        }
-       return ata_pci_sff_init_one(pdev, ppi, &pacpi_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(pdev, ppi, &pacpi_sht, NULL, 0);
 }
 
 static const struct pci_device_id pacpi_pci_tbl[] = {
index f306e10..794ec6e 100644 (file)
@@ -583,7 +583,10 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
                        ppi[0] = &info_20_udma;
        }
 
-       return ata_pci_sff_init_one(pdev, ppi, &ali_sht, NULL, 0);
+       if (!ppi[0]->mwdma_mask && !ppi[0]->udma_mask)
+               return ata_pci_sff_init_one(pdev, ppi, &ali_sht, NULL, 0);
+       else
+               return ata_pci_bmdma_init_one(pdev, ppi, &ali_sht, NULL, 0);
 }
 
 #ifdef CONFIG_PM
index d95eca9..620a07c 100644 (file)
@@ -574,7 +574,7 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        }
 
        /* And fire it up */
-       return ata_pci_sff_init_one(pdev, ppi, &amd_sht, hpriv, 0);
+       return ata_pci_bmdma_init_one(pdev, ppi, &amd_sht, hpriv, 0);
 }
 
 #ifdef CONFIG_PM
index 4d066d6..ba43f0f 100644 (file)
@@ -421,7 +421,7 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
 
        BUG_ON(ppi[0] == NULL);
 
-       return ata_pci_sff_init_one(pdev, ppi, &artop_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(pdev, ppi, &artop_sht, NULL, 0);
 }
 
 static const struct pci_device_id artop_pci_tbl[] = {
index 44d88b3..4375561 100644 (file)
@@ -246,8 +246,8 @@ static int atiixp_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
                if (!pci_test_config_bits(pdev, &atiixp_enable_bits[i]))
                        ppi[i] = &ata_dummy_port_info;
 
-       return ata_pci_sff_init_one(pdev, ppi, &atiixp_sht, NULL,
-                                               ATA_HOST_PARALLEL_SCAN);
+       return ata_pci_bmdma_init_one(pdev, ppi, &atiixp_sht, NULL,
+                                     ATA_HOST_PARALLEL_SCAN);
 }
 
 static const struct pci_device_id atiixp[] = {
index bb6e074..9529593 100644 (file)
@@ -525,7 +525,7 @@ static int atp867x_init_one(struct pci_dev *pdev,
 
        pci_set_master(pdev);
 
-       rc = ata_host_activate(host, pdev->irq, ata_sff_interrupt,
+       rc = ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
                                IRQF_SHARED, &atp867x_sht);
        if (rc)
                dev_printk(KERN_ERR, &pdev->dev, "failed to activate host\n");
index 6422cfd..9cae65d 100644 (file)
@@ -1214,7 +1214,7 @@ static unsigned int bfin_data_xfer(struct ata_device *dev, unsigned char *buf,
  *     bfin_irq_clear - Clear ATAPI interrupt.
  *     @ap: Port associated with this ATA transaction.
  *
- *     Note: Original code is ata_sff_irq_clear().
+ *     Note: Original code is ata_bmdma_irq_clear().
  */
 
 static void bfin_irq_clear(struct ata_port *ap)
index 4c81a71..9f5da1c 100644 (file)
@@ -367,7 +367,7 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
 #endif
 
-       return ata_pci_sff_init_one(pdev, ppi, &cmd64x_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(pdev, ppi, &cmd64x_sht, NULL, 0);
 }
 
 #ifdef CONFIG_PM
index 17c5f34..030952f 100644 (file)
@@ -221,7 +221,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
                        continue;
 
                rc = devm_request_irq(&pdev->dev, irq[ap->port_no],
-                                     ata_sff_interrupt, 0, DRV_NAME, host);
+                                     ata_bmdma_interrupt, 0, DRV_NAME, host);
                if (rc)
                        return rc;
 
index e809a42..f792330 100644 (file)
@@ -324,7 +324,7 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
                ppi[1] = &info_palmax_secondary;
 
        /* Now kick off ATA set up */
-       return ata_pci_sff_init_one(pdev, ppi, &cs5530_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(pdev, ppi, &cs5530_sht, NULL, 0);
 }
 
 #ifdef CONFIG_PM
index a02e645..03a9318 100644 (file)
@@ -198,7 +198,7 @@ static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id)
        rdmsr(ATAC_CH0D1_PIO, timings, dummy);
        if (CS5535_BAD_PIO(timings))
                wrmsr(ATAC_CH0D1_PIO, 0xF7F4F7F4UL, 0);
-       return ata_pci_sff_init_one(dev, ppi, &cs5535_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(dev, ppi, &cs5535_sht, NULL, 0);
 }
 
 static const struct pci_device_id cs5535[] = {
index 914ae35..21ee23f 100644 (file)
@@ -260,7 +260,7 @@ static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id)
                return -ENODEV;
        }
 
-       return ata_pci_sff_init_one(dev, ppi, &cs5536_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(dev, ppi, &cs5536_sht, NULL, 0);
 }
 
 static const struct pci_device_id cs5536[] = {
index 0fcc096..6d915b0 100644 (file)
@@ -138,7 +138,7 @@ static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *i
        if (PCI_FUNC(pdev->devfn) != 1)
                return -ENODEV;
 
-       return ata_pci_sff_init_one(pdev, ppi, &cy82c693_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(pdev, ppi, &cy82c693_sht, NULL, 0);
 }
 
 static const struct pci_device_id cy82c693[] = {
index 3bac0e0..a088347 100644 (file)
@@ -277,8 +277,8 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
                dev_printk(KERN_DEBUG, &pdev->dev,
                           "version " DRV_VERSION "\n");
 
-       return ata_pci_sff_init_one(pdev, ppi, &efar_sht, NULL,
-                                       ATA_HOST_PARALLEL_SCAN);
+       return ata_pci_bmdma_init_one(pdev, ppi, &efar_sht, NULL,
+                                     ATA_HOST_PARALLEL_SCAN);
 }
 
 static const struct pci_device_id efar_pci_tbl[] = {
index 8580eb3..7688868 100644 (file)
@@ -361,7 +361,7 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
                        break;
        }
        /* Now kick off ATA set up */
-       return ata_pci_sff_init_one(dev, ppi, &hpt36x_sht, hpriv, 0);
+       return ata_pci_bmdma_init_one(dev, ppi, &hpt36x_sht, hpriv, 0);
 }
 
 #ifdef CONFIG_PM
index 98b498b..9ae4c08 100644 (file)
@@ -987,7 +987,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
        }
 
        /* Now kick off ATA set up */
-       return ata_pci_sff_init_one(dev, ppi, &hpt37x_sht, private_data, 0);
+       return ata_pci_bmdma_init_one(dev, ppi, &hpt37x_sht, private_data, 0);
 }
 
 static const struct pci_device_id hpt37x[] = {
index 8b95aeb..32f3463 100644 (file)
@@ -548,7 +548,7 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
                outb(inb(iobase + 0x9c) | 0x04, iobase + 0x9c);
 
        /* Now kick off ATA set up */
-       return ata_pci_sff_init_one(dev, ppi, &hpt3x2n_sht, hpriv, 0);
+       return ata_pci_bmdma_init_one(dev, ppi, &hpt3x2n_sht, hpriv, 0);
 }
 
 static const struct pci_device_id hpt3x2n[] = {
index 727a81c..b63d5e2 100644 (file)
@@ -248,7 +248,7 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
                ata_port_pbar_desc(ap, 4, offset_cmd[i], "cmd");
        }
        pci_set_master(pdev);
-       return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
+       return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
                                 IRQF_SHARED, &hpt3x3_sht);
 }
 
index b56e8f7..9f2889f 100644 (file)
@@ -470,7 +470,7 @@ static int __devinit pata_icside_add_ports(struct pata_icside_info *info)
                pata_icside_setup_ioaddr(ap, info->base, info, info->port[i]);
        }
 
-       return ata_host_activate(host, ec->irq, ata_sff_interrupt, 0,
+       return ata_host_activate(host, ec->irq, ata_bmdma_interrupt, 0,
                                 &pata_icside_sht);
 }
 
index f971f0d..4d142a2 100644 (file)
@@ -273,7 +273,7 @@ static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *en
                dev_printk(KERN_DEBUG, &pdev->dev,
                           "version " DRV_VERSION "\n");
 
-       return ata_pci_sff_init_one(pdev, ppi, &it8213_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(pdev, ppi, &it8213_sht, NULL, 0);
 }
 
 static const struct pci_device_id it8213_pci_tbl[] = {
index 2bd2b00..bf88f71 100644 (file)
@@ -933,7 +933,7 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
                else
                        ppi[0] = &info_smart;
        }
-       return ata_pci_sff_init_one(pdev, ppi, &it821x_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(pdev, ppi, &it821x_sht, NULL, 0);
 }
 
 #ifdef CONFIG_PM
index 565e01e..cb3babb 100644 (file)
@@ -144,7 +144,7 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i
        };
        const struct ata_port_info *ppi[] = { &info, NULL };
 
-       return ata_pci_sff_init_one(pdev, ppi, &jmicron_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(pdev, ppi, &jmicron_sht, NULL, 0);
 }
 
 static const struct pci_device_id jmicron_pci_tbl[] = {
index b5b48e7..76640ac 100644 (file)
@@ -1110,7 +1110,7 @@ static int __devinit pata_macio_common_init(struct pata_macio_priv        *priv,
 
        /* Start it up */
        priv->irq = irq;
-       return ata_host_activate(priv->host, irq, ata_sff_interrupt, 0,
+       return ata_host_activate(priv->host, irq, ata_bmdma_interrupt, 0,
                                 &pata_macio_sht);
 }
 
index e8ca02e..dd38083 100644 (file)
@@ -153,7 +153,7 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i
                return -ENODEV;
        }
 #endif
-       return ata_pci_sff_init_one(pdev, ppi, &marvell_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(pdev, ppi, &marvell_sht, NULL, 0);
 }
 
 static const struct pci_device_id marvell_pci_tbl[] = {
index 36afe2c..f087ab5 100644 (file)
@@ -659,7 +659,7 @@ mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv,
        ata_port_desc(ap, "ata_regs 0x%lx", raw_ata_regs);
 
        /* activate host */
-       return ata_host_activate(host, priv->ata_irq, ata_sff_interrupt, 0,
+       return ata_host_activate(host, priv->ata_irq, ata_bmdma_interrupt, 0,
                                 &mpc52xx_ata_sht);
 }
 
index 94f979a..3eb921c 100644 (file)
@@ -82,7 +82,7 @@ static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *e
        ata_pci_bmdma_clear_simplex(pdev);
 
        /* And let the library code do the work */
-       return ata_pci_sff_init_one(pdev, port_info, &netcell_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(pdev, port_info, &netcell_sht, NULL, 0);
 }
 
 static const struct pci_device_id netcell_pci_tbl[] = {
index dd53a66..cc50bd0 100644 (file)
@@ -149,7 +149,7 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 
        ninja32_program(base);
        /* FIXME: Should we disable them at remove ? */
-       return ata_host_activate(host, dev->irq, ata_sff_interrupt,
+       return ata_host_activate(host, dev->irq, ata_bmdma_interrupt,
                                 IRQF_SHARED, &ninja32_sht);
 }
 
index fdbba2d..605f198 100644 (file)
@@ -380,7 +380,7 @@ static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *e
 
        ns87415_fixup(pdev);
 
-       return ata_pci_sff_init_one(pdev, ppi, &ns87415_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(pdev, ppi, &ns87415_sht, NULL, 0);
 }
 
 static const struct pci_device_id ns87415_pci_tbl[] = {
index 3001109..06ddd91 100644 (file)
@@ -749,20 +749,6 @@ static void octeon_cf_dev_config(struct ata_device *dev)
        dev->max_sectors = min(dev->max_sectors, 4095U);
 }
 
-/*
- * Trap if driver tries to do standard bmdma commands.  They are not
- * supported.
- */
-static void unreachable_qc(struct ata_queued_cmd *qc)
-{
-       BUG();
-}
-
-static u8 unreachable_port(struct ata_port *ap)
-{
-       BUG();
-}
-
 /*
  * We don't do ATAPI DMA so return 0.
  */
@@ -804,10 +790,6 @@ static struct ata_port_operations octeon_cf_ops = {
        .sff_dev_select         = octeon_cf_dev_select,
        .sff_irq_on             = octeon_cf_irq_on,
        .sff_irq_clear          = octeon_cf_irq_clear,
-       .bmdma_setup            = unreachable_qc,
-       .bmdma_start            = unreachable_qc,
-       .bmdma_stop             = unreachable_qc,
-       .bmdma_status           = unreachable_port,
        .cable_detect           = ata_cable_40wire,
        .set_piomode            = octeon_cf_set_piomode,
        .set_dmamode            = octeon_cf_set_dmamode,
index 988ef26..b811c16 100644 (file)
@@ -248,7 +248,7 @@ static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *e
                dev_printk(KERN_DEBUG, &pdev->dev,
                           "version " DRV_VERSION "\n");
 
-       return ata_pci_sff_init_one(pdev, ppi, &oldpiix_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(pdev, ppi, &oldpiix_sht, NULL, 0);
 }
 
 static const struct pci_device_id oldpiix_pci_tbl[] = {
index 76b7d12..0852cd0 100644 (file)
@@ -429,7 +429,7 @@ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id)
        if (optiplus_with_udma(dev))
                ppi[0] = &info_82c700_udma;
 
-       return ata_pci_sff_init_one(dev, ppi, &optidma_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(dev, ppi, &optidma_sht, NULL, 0);
 }
 
 static const struct pci_device_id optidma[] = {
index 09f1f22..b183511 100644 (file)
@@ -754,7 +754,7 @@ static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_de
                return -EIO;
 
        pci_set_master(pdev);
-       return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
+       return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
                                 IRQF_SHARED, &pdc2027x_sht);
 }
 
index fa1e2f3..c39f213 100644 (file)
@@ -337,7 +337,7 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id
                                return -ENODEV;
                }
        }
-       return ata_pci_sff_init_one(dev, ppi, &pdc202xx_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(dev, ppi, &pdc202xx_sht, NULL, 0);
 }
 
 static const struct pci_device_id pdc202xx[] = {
index 9816154..cb01bf9 100644 (file)
@@ -95,7 +95,7 @@ static int ata_tosh_init_one(struct pci_dev *dev, const struct pci_device_id *id
        };
        const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
        /* Just one port for the moment */
-       return ata_pci_sff_init_one(dev, ppi, &tosh_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(dev, ppi, &tosh_sht, NULL, 0);
 }
 
 static struct pci_device_id ata_tosh[] = {
index a5fa388..8574b31 100644 (file)
@@ -227,7 +227,7 @@ static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *e
                dev_printk(KERN_DEBUG, &pdev->dev,
                           "version " DRV_VERSION "\n");
 
-       return ata_pci_sff_init_one(pdev, ppi, &radisys_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(pdev, ppi, &radisys_sht, NULL, 0);
 }
 
 static const struct pci_device_id radisys_pci_tbl[] = {
index 37092cf..5fbe9b1 100644 (file)
@@ -344,7 +344,7 @@ static int __devinit rdc_init_one(struct pci_dev *pdev,
         */
        pci_read_config_dword(pdev, 0x54, &hpriv->saved_iocfg);
 
-       rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+       rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
        if (rc)
                return rc;
        host->private_data = hpriv;
@@ -354,7 +354,7 @@ static int __devinit rdc_init_one(struct pci_dev *pdev,
        host->flags |= ATA_HOST_PARALLEL_SCAN;
 
        pci_set_master(pdev);
-       return ata_pci_sff_activate_host(host, ata_sff_interrupt, &rdc_sht);
+       return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, &rdc_sht);
 }
 
 static void rdc_remove_one(struct pci_dev *pdev)
index 6b5b63a..e2c1825 100644 (file)
@@ -237,7 +237,7 @@ static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
        };
        const struct ata_port_info *ppi[] = { &info, NULL };
 
-       return ata_pci_sff_init_one(dev, ppi, &sc1200_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(dev, ppi, &sc1200_sht, NULL, 0);
 }
 
 static const struct pci_device_id sc1200[] = {
index 6f6193b..d9db3f8 100644 (file)
@@ -875,7 +875,7 @@ static void scc_postreset(struct ata_link *link, unsigned int *classes)
  *     scc_irq_clear - Clear PCI IDE BMDMA interrupt.
  *     @ap: Port associated with this ATA transaction.
  *
- *     Note: Original code is ata_sff_irq_clear().
+ *     Note: Original code is ata_bmdma_irq_clear().
  */
 
 static void scc_irq_clear (struct ata_port *ap)
@@ -1105,7 +1105,7 @@ static int scc_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc)
                return rc;
 
-       return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
+       return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
                                 IRQF_SHARED, &scc_sht);
 }
 
index 86b3d01..e97b32f 100644 (file)
@@ -179,7 +179,7 @@ static int __devinit sch_init_one(struct pci_dev *pdev,
                dev_printk(KERN_DEBUG, &pdev->dev,
                           "version " DRV_VERSION "\n");
 
-       return ata_pci_sff_init_one(pdev, ppi, &sch_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(pdev, ppi, &sch_sht, NULL, 0);
 }
 
 static int __init sch_init(void)
index 43ea389..86dd714 100644 (file)
@@ -460,7 +460,7 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id
        if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
                ata_pci_bmdma_clear_simplex(pdev);
 
-       return ata_pci_sff_init_one(pdev, ppi, &serverworks_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(pdev, ppi, &serverworks_sht, NULL, 0);
 }
 
 #ifdef CONFIG_PM
index 43faf10..d3190d7 100644 (file)
@@ -374,11 +374,11 @@ static int __devinit sil680_init_one(struct pci_dev *pdev,
        ata_sff_std_ports(&host->ports[1]->ioaddr);
 
        /* Register & activate */
-       return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
+       return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
                                 IRQF_SHARED, &sil680_sht);
 
 use_ioports:
-       return ata_pci_sff_init_one(pdev, ppi, &sil680_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(pdev, ppi, &sil680_sht, NULL, 0);
 }
 
 #ifdef CONFIG_PM
index b670803..60cea13 100644 (file)
@@ -826,7 +826,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 
        sis_fixup(pdev, chipset);
 
-       return ata_pci_sff_init_one(pdev, ppi, &sis_sht, chipset, 0);
+       return ata_pci_bmdma_init_one(pdev, ppi, &sis_sht, chipset, 0);
 }
 
 #ifdef CONFIG_PM
index 733b042..98548f6 100644 (file)
@@ -316,7 +316,7 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id
        val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16;
        pci_write_config_dword(dev, 0x40, val);
 
-       return ata_pci_sff_init_one(dev, ppi, &sl82c105_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(dev, ppi, &sl82c105_sht, NULL, 0);
 }
 
 static const struct pci_device_id sl82c105[] = {
index 48f5060..0d1f89e 100644 (file)
@@ -201,7 +201,7 @@ static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id)
        if (!printed_version++)
                dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
 
-       return ata_pci_sff_init_one(dev, ppi, &triflex_sht, NULL, 0);
+       return ata_pci_bmdma_init_one(dev, ppi, &triflex_sht, NULL, 0);
 }
 
 static const struct pci_device_id triflex[] = {
index 7e3e0a5..5e65988 100644 (file)
@@ -627,7 +627,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        }
 
        /* We have established the device type, now fire it up */
-       return ata_pci_sff_init_one(pdev, ppi, &via_sht, (void *)config, 0);
+       return ata_pci_bmdma_init_one(pdev, ppi, &via_sht, (void *)config, 0);
 }
 
 #ifdef CONFIG_PM
index f3471bc..a476cd9 100644 (file)
@@ -675,8 +675,6 @@ static struct ata_port_operations mv5_ops = {
        .freeze                 = mv_eh_freeze,
        .thaw                   = mv_eh_thaw,
        .hardreset              = mv_hardreset,
-       .error_handler          = ata_std_error_handler, /* avoid SFF EH */
-       .post_internal_cmd      = ATA_OP_NULL,
 
        .scr_read               = mv5_scr_read,
        .scr_write              = mv5_scr_write,
@@ -2813,7 +2811,7 @@ static void mv_port_intr(struct ata_port *ap, u32 port_cause)
        } else if (!edma_was_enabled) {
                struct ata_queued_cmd *qc = mv_get_active_qc(ap);
                if (qc)
-                       ata_sff_host_intr(ap, qc);
+                       ata_bmdma_port_intr(ap, qc);
                else
                        mv_unexpected_intr(ap, edma_was_enabled);
        }
index baa8f0d..6fd1147 100644 (file)
@@ -920,7 +920,7 @@ static int nv_host_intr(struct ata_port *ap, u8 irq_stat)
        }
 
        /* handle interrupt */
-       return ata_sff_host_intr(ap, qc);
+       return ata_bmdma_port_intr(ap, qc);
 }
 
 static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
@@ -1100,7 +1100,7 @@ static void nv_adma_irq_clear(struct ata_port *ap)
        u32 notifier_clears[2];
 
        if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) {
-               ata_sff_irq_clear(ap);
+               ata_bmdma_irq_clear(ap);
                return;
        }
 
@@ -1505,7 +1505,7 @@ static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance)
 
                qc = ata_qc_from_tag(ap, ap->link.active_tag);
                if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
-                       handled += ata_sff_host_intr(ap, qc);
+                       handled += ata_bmdma_port_intr(ap, qc);
                } else {
                        /*
                         * No request pending?  Clear interrupt status
@@ -2430,7 +2430,7 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        ppi[0] = &nv_port_info[type];
        ipriv = ppi[0]->private_data;
-       rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+       rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
        if (rc)
                return rc;
 
index d533b3d..daeebf1 100644 (file)
@@ -120,8 +120,6 @@ static void qs_host_stop(struct ata_host *host);
 static void qs_qc_prep(struct ata_queued_cmd *qc);
 static unsigned int qs_qc_issue(struct ata_queued_cmd *qc);
 static int qs_check_atapi_dma(struct ata_queued_cmd *qc);
-static void qs_bmdma_stop(struct ata_queued_cmd *qc);
-static u8 qs_bmdma_status(struct ata_port *ap);
 static void qs_freeze(struct ata_port *ap);
 static void qs_thaw(struct ata_port *ap);
 static int qs_prereset(struct ata_link *link, unsigned long deadline);
@@ -137,8 +135,6 @@ static struct ata_port_operations qs_ata_ops = {
        .inherits               = &ata_sff_port_ops,
 
        .check_atapi_dma        = qs_check_atapi_dma,
-       .bmdma_stop             = qs_bmdma_stop,
-       .bmdma_status           = qs_bmdma_status,
        .qc_prep                = qs_qc_prep,
        .qc_issue               = qs_qc_issue,
 
@@ -190,16 +186,6 @@ static int qs_check_atapi_dma(struct ata_queued_cmd *qc)
        return 1;       /* ATAPI DMA not supported */
 }
 
-static void qs_bmdma_stop(struct ata_queued_cmd *qc)
-{
-       /* nothing */
-}
-
-static u8 qs_bmdma_status(struct ata_port *ap)
-{
-       return 0;
-}
-
 static inline void qs_enter_reg_mode(struct ata_port *ap)
 {
        u8 __iomem *chan = qs_mmio_base(ap->host) + (ap->port_no * 0x4000);
@@ -454,7 +440,7 @@ static inline unsigned int qs_intr_mmio(struct ata_host *host)
                if (!pp || pp->state != qs_state_mmio)
                        continue;
                if (!(qc->tf.flags & ATA_TFLAG_POLLING))
-                       handled |= ata_sff_host_intr(ap, qc);
+                       handled |= ata_sff_port_intr(ap, qc);
        }
        return handled;
 }
index 2dda312..3a4f842 100644 (file)
@@ -503,7 +503,7 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
                goto err_hsm;
 
        /* ack bmdma irq events */
-       ata_sff_irq_clear(ap);
+       ata_bmdma_irq_clear(ap);
 
        /* kick HSM in the ass */
        ata_sff_hsm_move(ap, qc, status, 0);
@@ -584,7 +584,7 @@ static void sil_thaw(struct ata_port *ap)
 
        /* clear IRQ */
        ap->ops->sff_check_status(ap);
-       ata_sff_irq_clear(ap);
+       ata_bmdma_irq_clear(ap);
 
        /* turn on SATA IRQ if supported */
        if (!(ap->flags & SIL_FLAG_NO_SATA_IRQ))
index f8a91bf..2bfe3ae 100644 (file)
@@ -279,7 +279,7 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                break;
        }
 
-       rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+       rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
        if (rc)
                return rc;
 
@@ -308,7 +308,7 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        pci_set_master(pdev);
        pci_intx(pdev, 1);
-       return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
+       return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
                                 IRQF_SHARED, &sis_sht);
 }
 
index 101fd6a..7d9db4a 100644 (file)
@@ -502,7 +502,7 @@ static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *en
        writel(0x0, mmio_base + K2_SATA_SIM_OFFSET);
 
        pci_set_master(pdev);
-       return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
+       return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
                                 IRQF_SHARED, &k2_sata_sht);
 }
 
index d8dac17..b8578c3 100644 (file)
@@ -242,7 +242,7 @@ static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        pci_set_master(pdev);
        pci_intx(pdev, 1);
-       return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
+       return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
                                 IRQF_SHARED, &uli_sht);
 }
 
index 08f6549..101d8c2 100644 (file)
@@ -308,7 +308,7 @@ static void svia_noop_freeze(struct ata_port *ap)
         * certain way.  Leave it alone and just clear pending IRQ.
         */
        ap->ops->sff_check_status(ap);
-       ata_sff_irq_clear(ap);
+       ata_bmdma_irq_clear(ap);
 }
 
 /**
@@ -463,7 +463,7 @@ static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
        struct ata_host *host;
        int rc;
 
-       rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+       rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
        if (rc)
                return rc;
        *r_host = host;
@@ -520,7 +520,7 @@ static int vt8251_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
        struct ata_host *host;
        int i, rc;
 
-       rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+       rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
        if (rc)
                return rc;
        *r_host = host;
@@ -628,7 +628,7 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        svia_configure(pdev);
 
        pci_set_master(pdev);
-       return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
+       return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
                                 IRQF_SHARED, &svia_sht);
 }
 
index 2107952..b777176 100644 (file)
@@ -245,7 +245,7 @@ static void vsc_port_intr(u8 port_status, struct ata_port *ap)
 
        qc = ata_qc_from_tag(ap, ap->link.active_tag);
        if (qc && likely(!(qc->tf.flags & ATA_TFLAG_POLLING)))
-               handled = ata_sff_host_intr(ap, qc);
+               handled = ata_bmdma_port_intr(ap, qc);
 
        /* We received an interrupt during a polled command,
         * or some other spurious condition.  Interrupt reporting
index 606048b..85c004a 100644 (file)
@@ -305,8 +305,7 @@ static int ps3flash_flush(struct file *file, fl_owner_t id)
        return ps3flash_writeback(ps3flash_dev);
 }
 
-static int ps3flash_fsync(struct file *file, struct dentry *dentry,
-                         int datasync)
+static int ps3flash_fsync(struct file *file, int datasync)
 {
        return ps3flash_writeback(ps3flash_dev);
 }
index 72ebb3f..4dfa6b9 100644 (file)
@@ -189,8 +189,7 @@ static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin)
        return new_offset;
 }
 
-static int vol_cdev_fsync(struct file *file, struct dentry *dentry,
-                         int datasync)
+static int vol_cdev_fsync(struct file *file, int datasync)
 {
        struct ubi_volume_desc *desc = file->private_data;
        struct ubi_device *ubi = desc->vol->ubi;
index 82eaf65..ea9b7a0 100644 (file)
@@ -551,8 +551,7 @@ static irqreturn_t el16_interrupt(int irq, void *dev_id)
        void __iomem *shmem;
 
        if (dev == NULL) {
-               pr_err("%s: net_interrupt(): irq %d for unknown device.\n",
-                       dev->name, irq);
+               pr_err("net_interrupt(): irq %d for unknown device.\n", irq);
                return IRQ_NONE;
        }
 
index c911bfb..9d11dbf 100644 (file)
@@ -294,7 +294,7 @@ int be_cmd_POST(struct be_adapter *adapter)
                } else {
                        return 0;
                }
-       } while (timeout < 20);
+       } while (timeout < 40);
 
        dev_err(&adapter->pdev->dev, "POST timeout; stage=0x%x\n", stage);
        return -1;
index aa065c7..54b1427 100644 (file)
@@ -1861,7 +1861,7 @@ static int be_setup(struct be_adapter *adapter)
                                goto if_destroy;
                        }
                        vf++;
-               } while (vf < num_vfs);
+               }
        } else if (!be_physfn(adapter)) {
                status = be_cmd_mac_addr_query(adapter, mac,
                        MAC_ADDRESS_TYPE_NETWORK, false, adapter->if_handle);
index be90d35..fe92566 100644 (file)
@@ -3367,13 +3367,9 @@ static int cnic_cm_shutdown(struct cnic_dev *dev)
 
 static void cnic_init_context(struct cnic_dev *dev, u32 cid)
 {
-       struct cnic_local *cp = dev->cnic_priv;
        u32 cid_addr;
        int i;
 
-       if (CHIP_NUM(cp) == CHIP_NUM_5709)
-               return;
-
        cid_addr = GET_CID_ADDR(cid);
 
        for (i = 0; i < CTX_SIZE; i += 4)
@@ -3530,14 +3526,11 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev)
 
        sb_id = cp->status_blk_num;
        tx_cid = 20;
-       cnic_init_context(dev, tx_cid);
-       cnic_init_context(dev, tx_cid + 1);
        cp->tx_cons_ptr = &s_blk->status_tx_quick_consumer_index2;
        if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) {
                struct status_block_msix *sblk = cp->status_blk.bnx2;
 
                tx_cid = TX_TSS_CID + sb_id - 1;
-               cnic_init_context(dev, tx_cid);
                CNIC_WR(dev, BNX2_TSCH_TSS_CFG, (sb_id << 24) |
                        (TX_TSS_CID << 7));
                cp->tx_cons_ptr = &sblk->status_tx_quick_consumer_index;
@@ -3556,6 +3549,9 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev)
                offset2 = BNX2_L2CTX_TBDR_BHADDR_HI_XI;
                offset3 = BNX2_L2CTX_TBDR_BHADDR_LO_XI;
        } else {
+               cnic_init_context(dev, tx_cid);
+               cnic_init_context(dev, tx_cid + 1);
+
                offset0 = BNX2_L2CTX_TYPE;
                offset1 = BNX2_L2CTX_CMD_TYPE;
                offset2 = BNX2_L2CTX_TBDR_BHADDR_HI;
index 110c620..0c55177 100644 (file)
@@ -12,8 +12,8 @@
 #ifndef CNIC_IF_H
 #define CNIC_IF_H
 
-#define CNIC_MODULE_VERSION    "2.1.1"
-#define CNIC_MODULE_RELDATE    "Feb 22, 2010"
+#define CNIC_MODULE_VERSION    "2.1.2"
+#define CNIC_MODULE_RELDATE    "May 26, 2010"
 
 #define CNIC_ULP_RDMA          0
 #define CNIC_ULP_ISCSI         1
index 326465f..ddf7a86 100644 (file)
@@ -681,6 +681,8 @@ static int fec_enet_mii_probe(struct net_device *dev)
        struct phy_device *phy_dev = NULL;
        int phy_addr;
 
+       fep->phy_dev = NULL;
+
        /* find the first phy */
        for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
                if (fep->mii_bus->phy_map[phy_addr]) {
@@ -711,6 +713,11 @@ static int fec_enet_mii_probe(struct net_device *dev)
        fep->link = 0;
        fep->full_duplex = 0;
 
+       printk(KERN_INFO "%s: Freescale FEC PHY driver [%s] "
+               "(mii_bus:phy_addr=%s, irq=%d)\n", dev->name,
+               fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev),
+               fep->phy_dev->irq);
+
        return 0;
 }
 
@@ -756,13 +763,8 @@ static int fec_enet_mii_init(struct platform_device *pdev)
        if (mdiobus_register(fep->mii_bus))
                goto err_out_free_mdio_irq;
 
-       if (fec_enet_mii_probe(dev) != 0)
-               goto err_out_unregister_bus;
-
        return 0;
 
-err_out_unregister_bus:
-       mdiobus_unregister(fep->mii_bus);
 err_out_free_mdio_irq:
        kfree(fep->mii_bus->irq);
 err_out_free_mdiobus:
@@ -915,7 +917,12 @@ fec_enet_open(struct net_device *dev)
        if (ret)
                return ret;
 
-       /* schedule a link state check */
+       /* Probe and connect to PHY when open the interface */
+       ret = fec_enet_mii_probe(dev);
+       if (ret) {
+               fec_enet_free_buffers(dev);
+               return ret;
+       }
        phy_start(fep->phy_dev);
        netif_start_queue(dev);
        fep->opened = 1;
@@ -929,10 +936,12 @@ fec_enet_close(struct net_device *dev)
 
        /* Don't know what to do yet. */
        fep->opened = 0;
-       phy_stop(fep->phy_dev);
        netif_stop_queue(dev);
        fec_stop(dev);
 
+       if (fep->phy_dev)
+               phy_disconnect(fep->phy_dev);
+
         fec_enet_free_buffers(dev);
 
        return 0;
@@ -1316,11 +1325,6 @@ fec_probe(struct platform_device *pdev)
        if (ret)
                goto failed_register;
 
-       printk(KERN_INFO "%s: Freescale FEC PHY driver [%s] "
-               "(mii_bus:phy_addr=%s, irq=%d)\n", ndev->name,
-               fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev),
-               fep->phy_dev->irq);
-
        return 0;
 
 failed_register:
index 694132e..4e7d1d0 100644 (file)
@@ -1151,8 +1151,7 @@ static int __init yam_init_driver(void)
                dev = alloc_netdev(sizeof(struct yam_port), name,
                                   yam_setup);
                if (!dev) {
-                       printk(KERN_ERR "yam: cannot allocate net device %s\n",
-                              dev->name);
+                       pr_err("yam: cannot allocate net device\n");
                        err = -ENOMEM;
                        goto error;
                }
index c033584..522abe2 100644 (file)
@@ -295,6 +295,10 @@ This option defaults to enabled (set) */
 
 #define MULTICAST_CAM_TABLE_NUM 4
 
+/* TEMAC Synthesis features */
+#define TEMAC_FEATURE_RX_CSUM  (1 << 0)
+#define TEMAC_FEATURE_TX_CSUM  (1 << 1)
+
 /* TX/RX CURDESC_PTR points to first descriptor */
 /* TX/RX TAILDESC_PTR points to last descriptor in linked list */
 
@@ -353,6 +357,7 @@ struct temac_local {
        struct mutex indirect_mutex;
        u32 options;                    /* Current options word */
        int last_link;
+       unsigned int temac_features;
 
        /* Buffer descriptors */
        struct cdmac_bd *tx_bd_v;
index fa7620e..52dcc84 100644 (file)
@@ -245,7 +245,7 @@ static int temac_dma_bd_init(struct net_device *ndev)
                                          CHNL_CTRL_IRQ_COAL_EN);
        /* 0x10220483 */
        /* 0x00100483 */
-       lp->dma_out(lp, RX_CHNL_CTRL, 0xff010000 |
+       lp->dma_out(lp, RX_CHNL_CTRL, 0xff070000 |
                                          CHNL_CTRL_IRQ_EN |
                                          CHNL_CTRL_IRQ_DLY_EN |
                                          CHNL_CTRL_IRQ_COAL_EN |
@@ -574,6 +574,10 @@ static void temac_start_xmit_done(struct net_device *ndev)
                if (cur_p->app4)
                        dev_kfree_skb_irq((struct sk_buff *)cur_p->app4);
                cur_p->app0 = 0;
+               cur_p->app1 = 0;
+               cur_p->app2 = 0;
+               cur_p->app3 = 0;
+               cur_p->app4 = 0;
 
                ndev->stats.tx_packets++;
                ndev->stats.tx_bytes += cur_p->len;
@@ -589,6 +593,29 @@ static void temac_start_xmit_done(struct net_device *ndev)
        netif_wake_queue(ndev);
 }
 
+static inline int temac_check_tx_bd_space(struct temac_local *lp, int num_frag)
+{
+       struct cdmac_bd *cur_p;
+       int tail;
+
+       tail = lp->tx_bd_tail;
+       cur_p = &lp->tx_bd_v[tail];
+
+       do {
+               if (cur_p->app0)
+                       return NETDEV_TX_BUSY;
+
+               tail++;
+               if (tail >= TX_BD_NUM)
+                       tail = 0;
+
+               cur_p = &lp->tx_bd_v[tail];
+               num_frag--;
+       } while (num_frag >= 0);
+
+       return 0;
+}
+
 static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 {
        struct temac_local *lp = netdev_priv(ndev);
@@ -603,7 +630,7 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        start_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail;
        cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
 
-       if (cur_p->app0 & STS_CTRL_APP0_CMPLT) {
+       if (temac_check_tx_bd_space(lp, num_frag)) {
                if (!netif_queue_stopped(ndev)) {
                        netif_stop_queue(ndev);
                        return NETDEV_TX_BUSY;
@@ -613,29 +640,14 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 
        cur_p->app0 = 0;
        if (skb->ip_summed == CHECKSUM_PARTIAL) {
-               const struct iphdr *ip = ip_hdr(skb);
-               int length = 0, start = 0, insert = 0;
-
-               switch (ip->protocol) {
-               case IPPROTO_TCP:
-                       start = sizeof(struct iphdr) + ETH_HLEN;
-                       insert = sizeof(struct iphdr) + ETH_HLEN + 16;
-                       length = ip->tot_len - sizeof(struct iphdr);
-                       break;
-               case IPPROTO_UDP:
-                       start = sizeof(struct iphdr) + ETH_HLEN;
-                       insert = sizeof(struct iphdr) + ETH_HLEN + 6;
-                       length = ip->tot_len - sizeof(struct iphdr);
-                       break;
-               default:
-                       break;
-               }
-               cur_p->app1 = ((start << 16) | insert);
-               cur_p->app2 = csum_tcpudp_magic(ip->saddr, ip->daddr,
-                                               length, ip->protocol, 0);
-               skb->data[insert] = 0;
-               skb->data[insert + 1] = 0;
+               unsigned int csum_start_off = skb_transport_offset(skb);
+               unsigned int csum_index_off = csum_start_off + skb->csum_offset;
+
+               cur_p->app0 |= 1; /* TX Checksum Enabled */
+               cur_p->app1 = (csum_start_off << 16) | csum_index_off;
+               cur_p->app2 = 0;  /* initial checksum seed */
        }
+
        cur_p->app0 |= STS_CTRL_APP0_SOP;
        cur_p->len = skb_headlen(skb);
        cur_p->phys = dma_map_single(ndev->dev.parent, skb->data, skb->len,
@@ -699,6 +711,15 @@ static void ll_temac_recv(struct net_device *ndev)
                skb->protocol = eth_type_trans(skb, ndev);
                skb->ip_summed = CHECKSUM_NONE;
 
+               /* if we're doing rx csum offload, set it up */
+               if (((lp->temac_features & TEMAC_FEATURE_RX_CSUM) != 0) &&
+                       (skb->protocol == __constant_htons(ETH_P_IP)) &&
+                       (skb->len > 64)) {
+
+                       skb->csum = cur_p->app3 & 0xFFFF;
+                       skb->ip_summed = CHECKSUM_COMPLETE;
+               }
+
                netif_rx(skb);
 
                ndev->stats.rx_packets++;
@@ -883,6 +904,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
        struct temac_local *lp;
        struct net_device *ndev;
        const void *addr;
+       __be32 *p;
        int size, rc = 0;
 
        /* Init network device structure */
@@ -926,6 +948,18 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
                goto nodev;
        }
 
+       /* Setup checksum offload, but default to off if not specified */
+       lp->temac_features = 0;
+       p = (__be32 *)of_get_property(op->dev.of_node, "xlnx,txcsum", NULL);
+       if (p && be32_to_cpu(*p)) {
+               lp->temac_features |= TEMAC_FEATURE_TX_CSUM;
+               /* Can checksum TCP/UDP over IPv4. */
+               ndev->features |= NETIF_F_IP_CSUM;
+       }
+       p = (__be32 *)of_get_property(op->dev.of_node, "xlnx,rxcsum", NULL);
+       if (p && be32_to_cpu(*p))
+               lp->temac_features |= TEMAC_FEATURE_RX_CSUM;
+
        /* Find the DMA node, map the DMA registers, and decode the DMA IRQs */
        np = of_parse_phandle(op->dev.of_node, "llink-connected", 0);
        if (!np) {
@@ -950,7 +984,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
 
        lp->rx_irq = irq_of_parse_and_map(np, 0);
        lp->tx_irq = irq_of_parse_and_map(np, 1);
-       if (!lp->rx_irq || !lp->tx_irq) {
+       if ((lp->rx_irq == NO_IRQ) || (lp->tx_irq == NO_IRQ)) {
                dev_err(&op->dev, "could not determine irqs\n");
                rc = -ENOMEM;
                goto nodev;
index 9286e86..e92595e 100644 (file)
@@ -880,7 +880,7 @@ static struct inode *pohmelfs_alloc_inode(struct super_block *sb)
 /*
  * We want fsync() to work on POHMELFS.
  */
-static int pohmelfs_fsync(struct file *file, struct dentry *dentry, int datasync)
+static int pohmelfs_fsync(struct file *file, int datasync)
 {
        struct inode *inode = file->f_mapping->host;
        struct writeback_control wbc = {
index 6b8bf8c..43abf55 100644 (file)
@@ -794,7 +794,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
 }
 
 static int
-printer_fsync(struct file *fd, struct dentry *dentry, int datasync)
+printer_fsync(struct file *fd, int datasync)
 {
        struct printer_dev      *dev = fd->private_data;
        unsigned long           flags;
index aa88911..0f41c91 100644 (file)
@@ -593,17 +593,17 @@ static long vhost_net_ioctl(struct file *f, unsigned int ioctl,
        int r;
        switch (ioctl) {
        case VHOST_NET_SET_BACKEND:
-               r = copy_from_user(&backend, argp, sizeof backend);
-               if (r < 0)
-                       return r;
+               if (copy_from_user(&backend, argp, sizeof backend))
+                       return -EFAULT;
                return vhost_net_set_backend(n, backend.index, backend.fd);
        case VHOST_GET_FEATURES:
                features = VHOST_FEATURES;
-               return copy_to_user(featurep, &features, sizeof features);
+               if (copy_to_user(featurep, &features, sizeof features))
+                       return -EFAULT;
+               return 0;
        case VHOST_SET_FEATURES:
-               r = copy_from_user(&features, featurep, sizeof features);
-               if (r < 0)
-                       return r;
+               if (copy_from_user(&features, featurep, sizeof features))
+                       return -EFAULT;
                if (features & ~VHOST_FEATURES)
                        return -EOPNOTSUPP;
                return vhost_net_set_features(n, features);
index c6fb8e9..3b83382 100644 (file)
@@ -320,10 +320,8 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
 {
        struct vhost_memory mem, *newmem, *oldmem;
        unsigned long size = offsetof(struct vhost_memory, regions);
-       long r;
-       r = copy_from_user(&mem, m, size);
-       if (r)
-               return r;
+       if (copy_from_user(&mem, m, size))
+               return -EFAULT;
        if (mem.padding)
                return -EOPNOTSUPP;
        if (mem.nregions > VHOST_MEMORY_MAX_NREGIONS)
@@ -333,15 +331,16 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
                return -ENOMEM;
 
        memcpy(newmem, &mem, size);
-       r = copy_from_user(newmem->regions, m->regions,
-                          mem.nregions * sizeof *m->regions);
-       if (r) {
+       if (copy_from_user(newmem->regions, m->regions,
+                          mem.nregions * sizeof *m->regions)) {
                kfree(newmem);
-               return r;
+               return -EFAULT;
        }
 
-       if (!memory_access_ok(d, newmem, vhost_has_feature(d, VHOST_F_LOG_ALL)))
+       if (!memory_access_ok(d, newmem, vhost_has_feature(d, VHOST_F_LOG_ALL))) {
+               kfree(newmem);
                return -EFAULT;
+       }
        oldmem = d->memory;
        rcu_assign_pointer(d->memory, newmem);
        synchronize_rcu();
@@ -374,7 +373,7 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
        r = get_user(idx, idxp);
        if (r < 0)
                return r;
-       if (idx > d->nvqs)
+       if (idx >= d->nvqs)
                return -ENOBUFS;
 
        vq = d->vqs + idx;
@@ -389,9 +388,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
                        r = -EBUSY;
                        break;
                }
-               r = copy_from_user(&s, argp, sizeof s);
-               if (r < 0)
+               if (copy_from_user(&s, argp, sizeof s)) {
+                       r = -EFAULT;
                        break;
+               }
                if (!s.num || s.num > 0xffff || (s.num & (s.num - 1))) {
                        r = -EINVAL;
                        break;
@@ -405,9 +405,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
                        r = -EBUSY;
                        break;
                }
-               r = copy_from_user(&s, argp, sizeof s);
-               if (r < 0)
+               if (copy_from_user(&s, argp, sizeof s)) {
+                       r = -EFAULT;
                        break;
+               }
                if (s.num > 0xffff) {
                        r = -EINVAL;
                        break;
@@ -419,12 +420,14 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
        case VHOST_GET_VRING_BASE:
                s.index = idx;
                s.num = vq->last_avail_idx;
-               r = copy_to_user(argp, &s, sizeof s);
+               if (copy_to_user(argp, &s, sizeof s))
+                       r = -EFAULT;
                break;
        case VHOST_SET_VRING_ADDR:
-               r = copy_from_user(&a, argp, sizeof a);
-               if (r < 0)
+               if (copy_from_user(&a, argp, sizeof a)) {
+                       r = -EFAULT;
                        break;
+               }
                if (a.flags & ~(0x1 << VHOST_VRING_F_LOG)) {
                        r = -EOPNOTSUPP;
                        break;
@@ -477,9 +480,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
                vq->used = (void __user *)(unsigned long)a.used_user_addr;
                break;
        case VHOST_SET_VRING_KICK:
-               r = copy_from_user(&f, argp, sizeof f);
-               if (r < 0)
+               if (copy_from_user(&f, argp, sizeof f)) {
+                       r = -EFAULT;
                        break;
+               }
                eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd);
                if (IS_ERR(eventfp)) {
                        r = PTR_ERR(eventfp);
@@ -492,9 +496,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
                        filep = eventfp;
                break;
        case VHOST_SET_VRING_CALL:
-               r = copy_from_user(&f, argp, sizeof f);
-               if (r < 0)
+               if (copy_from_user(&f, argp, sizeof f)) {
+                       r = -EFAULT;
                        break;
+               }
                eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd);
                if (IS_ERR(eventfp)) {
                        r = PTR_ERR(eventfp);
@@ -510,9 +515,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
                        filep = eventfp;
                break;
        case VHOST_SET_VRING_ERR:
-               r = copy_from_user(&f, argp, sizeof f);
-               if (r < 0)
+               if (copy_from_user(&f, argp, sizeof f)) {
+                       r = -EFAULT;
                        break;
+               }
                eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd);
                if (IS_ERR(eventfp)) {
                        r = PTR_ERR(eventfp);
@@ -575,9 +581,10 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, unsigned long arg)
                r = vhost_set_memory(d, argp);
                break;
        case VHOST_SET_LOG_BASE:
-               r = copy_from_user(&p, argp, sizeof p);
-               if (r < 0)
+               if (copy_from_user(&p, argp, sizeof p)) {
+                       r = -EFAULT;
                        break;
+               }
                if ((u64)(unsigned long)p != p) {
                        r = -EFAULT;
                        break;
index 1105a59..073c9b4 100644 (file)
@@ -66,7 +66,7 @@ static int fb_deferred_io_fault(struct vm_area_struct *vma,
        return 0;
 }
 
-int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, int datasync)
+int fb_deferred_io_fsync(struct file *file, int datasync)
 {
        struct fb_info *info = file->private_data;
 
index 25b300e..2bedc6c 100644 (file)
@@ -257,15 +257,13 @@ v9fs_file_write(struct file *filp, const char __user * data,
        return total;
 }
 
-static int v9fs_file_fsync(struct file *filp, struct dentry *dentry,
-                                       int datasync)
+static int v9fs_file_fsync(struct file *filp, int datasync)
 {
        struct p9_fid *fid;
        struct p9_wstat wstat;
        int retval;
 
-       P9_DPRINTK(P9_DEBUG_VFS, "filp %p dentry %p datasync %x\n", filp,
-                                               dentry, datasync);
+       P9_DPRINTK(P9_DEBUG_VFS, "filp %p datasync %x\n", filp, datasync);
 
        fid = filp->private_data;
        v9fs_blank_wstat(&wstat);
index 23aa52f..f4287e4 100644 (file)
@@ -197,7 +197,7 @@ const struct file_operations adfs_dir_operations = {
        .read           = generic_read_dir,
        .llseek         = generic_file_llseek,
        .readdir        = adfs_readdir,
-       .fsync          = simple_fsync,
+       .fsync          = generic_file_fsync,
 };
 
 static int
index 005ea34..a36da53 100644 (file)
@@ -26,7 +26,7 @@ const struct file_operations adfs_file_operations = {
        .read           = do_sync_read,
        .aio_read       = generic_file_aio_read,
        .mmap           = generic_file_mmap,
-       .fsync          = simple_fsync,
+       .fsync          = generic_file_fsync,
        .write          = do_sync_write,
        .aio_write      = generic_file_aio_write,
        .splice_read    = generic_file_splice_read,
index 0f5e309..6f850b0 100644 (file)
@@ -322,8 +322,9 @@ adfs_notify_change(struct dentry *dentry, struct iattr *attr)
        if (error)
                goto out;
 
+       /* XXX: this is missing some actual on-disk truncation.. */
        if (ia_valid & ATTR_SIZE)
-               error = vmtruncate(inode, attr->ia_size);
+               error = simple_setsize(inode, attr->ia_size);
 
        if (error)
                goto out;
index 861dae6..f05b615 100644 (file)
@@ -183,7 +183,7 @@ extern int                   affs_add_entry(struct inode *dir, struct inode *inode, struct dent
 
 void           affs_free_prealloc(struct inode *inode);
 extern void    affs_truncate(struct inode *);
-int            affs_file_fsync(struct file *, struct dentry *, int);
+int            affs_file_fsync(struct file *, int);
 
 /* dir.c */
 
index 184e55c..322710c 100644 (file)
@@ -916,9 +916,9 @@ affs_truncate(struct inode *inode)
        affs_free_prealloc(inode);
 }
 
-int affs_file_fsync(struct file *filp, struct dentry *dentry, int datasync)
+int affs_file_fsync(struct file *filp, int datasync)
 {
-       struct inode * inode = dentry->d_inode;
+       struct inode *inode = filp->f_mapping->host;
        int ret, err;
 
        ret = write_inode_now(inode, 0);
index 807f284..5f679b7 100644 (file)
@@ -740,7 +740,7 @@ extern void afs_pages_written_back(struct afs_vnode *, struct afs_call *);
 extern ssize_t afs_file_write(struct kiocb *, const struct iovec *,
                              unsigned long, loff_t);
 extern int afs_writeback_all(struct afs_vnode *);
-extern int afs_fsync(struct file *, struct dentry *, int);
+extern int afs_fsync(struct file *, int);
 
 
 /*****************************************************************************/
index 3bed54a..3dab9e9 100644 (file)
@@ -701,8 +701,9 @@ int afs_writeback_all(struct afs_vnode *vnode)
  * - the return status from this call provides a reliable indication of
  *   whether any write errors occurred for this process.
  */
-int afs_fsync(struct file *file, struct dentry *dentry, int datasync)
+int afs_fsync(struct file *file, int datasync)
 {
+       struct dentry *dentry = file->f_path.dentry;
        struct afs_writeback *wb, *xwb;
        struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
        int ret;
index 48fdeeb..1ccf25c 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -527,7 +527,7 @@ static void aio_fput_routine(struct work_struct *data)
 
                /* Complete the fput(s) */
                if (req->ki_filp != NULL)
-                       __fput(req->ki_filp);
+                       fput(req->ki_filp);
 
                /* Link the iocb into the context's free list */
                spin_lock_irq(&ctx->ctx_lock);
@@ -560,11 +560,11 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
 
        /*
         * Try to optimize the aio and eventfd file* puts, by avoiding to
-        * schedule work in case it is not __fput() time. In normal cases,
+        * schedule work in case it is not final fput() time. In normal cases,
         * we would not be holding the last reference to the file*, so
         * this function will be executed w/out any aio kthread wakeup.
         */
-       if (unlikely(atomic_long_dec_and_test(&req->ki_filp->f_count))) {
+       if (unlikely(!fput_atomic(req->ki_filp))) {
                get_ioctx(ctx);
                spin_lock(&fput_lock);
                list_add(&req->ki_list, &fput_head);
index 9bd4b38..e4b75d6 100644 (file)
@@ -205,7 +205,7 @@ static struct inode *anon_inode_mkinode(void)
         * that it already _is_ on the dirty list.
         */
        inode->i_state = I_DIRTY;
-       inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR;
+       inode->i_mode = S_IRUSR | S_IWUSR;
        inode->i_uid = current_fsuid();
        inode->i_gid = current_fsgid();
        inode->i_flags |= S_PRIVATE;
index 0815e93..b4fa3b0 100644 (file)
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -67,14 +67,14 @@ EXPORT_SYMBOL(inode_change_ok);
  * @offset:    the new size to assign to the inode
  * @Returns:   0 on success, -ve errno on failure
  *
+ * inode_newsize_ok must be called with i_mutex held.
+ *
  * inode_newsize_ok will check filesystem limits and ulimits to check that the
  * new inode size is within limits. inode_newsize_ok will also send SIGXFSZ
  * when necessary. Caller must not proceed with inode size change if failure is
  * returned. @inode must be a file (not directory), with appropriate
  * permissions to allow truncate (inode_newsize_ok does NOT check these
  * conditions).
- *
- * inode_newsize_ok must be called with i_mutex held.
  */
 int inode_newsize_ok(const struct inode *inode, loff_t offset)
 {
@@ -104,17 +104,25 @@ out_big:
 }
 EXPORT_SYMBOL(inode_newsize_ok);
 
-int inode_setattr(struct inode * inode, struct iattr * attr)
+/**
+ * generic_setattr - copy simple metadata updates into the generic inode
+ * @inode:     the inode to be updated
+ * @attr:      the new attributes
+ *
+ * generic_setattr must be called with i_mutex held.
+ *
+ * generic_setattr updates the inode's metadata with that specified
+ * in attr. Noticably missing is inode size update, which is more complex
+ * as it requires pagecache updates. See simple_setsize.
+ *
+ * The inode is not marked as dirty after this operation. The rationale is
+ * that for "simple" filesystems, the struct inode is the inode storage.
+ * The caller is free to mark the inode dirty afterwards if needed.
+ */
+void generic_setattr(struct inode *inode, const struct iattr *attr)
 {
        unsigned int ia_valid = attr->ia_valid;
 
-       if (ia_valid & ATTR_SIZE &&
-           attr->ia_size != i_size_read(inode)) {
-               int error = vmtruncate(inode, attr->ia_size);
-               if (error)
-                       return error;
-       }
-
        if (ia_valid & ATTR_UID)
                inode->i_uid = attr->ia_uid;
        if (ia_valid & ATTR_GID)
@@ -135,6 +143,28 @@ int inode_setattr(struct inode * inode, struct iattr * attr)
                        mode &= ~S_ISGID;
                inode->i_mode = mode;
        }
+}
+EXPORT_SYMBOL(generic_setattr);
+
+/*
+ * note this function is deprecated, the new truncate sequence should be
+ * used instead -- see eg. simple_setsize, generic_setattr.
+ */
+int inode_setattr(struct inode *inode, const struct iattr *attr)
+{
+       unsigned int ia_valid = attr->ia_valid;
+
+       if (ia_valid & ATTR_SIZE &&
+           attr->ia_size != i_size_read(inode)) {
+               int error;
+
+               error = vmtruncate(inode, attr->ia_size);
+               if (error)
+                       return error;
+       }
+
+       generic_setattr(inode, attr);
+
        mark_inode_dirty(inode);
 
        return 0;
index a05287a..52e59bf 100644 (file)
@@ -93,8 +93,7 @@ static int bad_file_release(struct inode *inode, struct file *filp)
        return -EIO;
 }
 
-static int bad_file_fsync(struct file *file, struct dentry *dentry,
-                       int datasync)
+static int bad_file_fsync(struct file *file, int datasync)
 {
        return -EIO;
 }
index 8f73841..d967e05 100644 (file)
@@ -78,7 +78,7 @@ static int bfs_readdir(struct file *f, void *dirent, filldir_t filldir)
 const struct file_operations bfs_dir_operations = {
        .read           = generic_read_dir,
        .readdir        = bfs_readdir,
-       .fsync          = simple_fsync,
+       .fsync          = generic_file_fsync,
        .llseek         = generic_file_llseek,
 };
 
index 26e5f50..7346c96 100644 (file)
@@ -172,8 +172,9 @@ blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
        struct file *file = iocb->ki_filp;
        struct inode *inode = file->f_mapping->host;
 
-       return blockdev_direct_IO_no_locking(rw, iocb, inode, I_BDEV(inode),
-                               iov, offset, nr_segs, blkdev_get_blocks, NULL);
+       return blockdev_direct_IO_no_locking_newtrunc(rw, iocb, inode,
+                               I_BDEV(inode), iov, offset, nr_segs,
+                               blkdev_get_blocks, NULL);
 }
 
 int __sync_blockdev(struct block_device *bdev, int wait)
@@ -309,8 +310,8 @@ static int blkdev_write_begin(struct file *file, struct address_space *mapping,
                        struct page **pagep, void **fsdata)
 {
        *pagep = NULL;
-       return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
-                               blkdev_get_block);
+       return block_write_begin_newtrunc(file, mapping, pos, len, flags,
+                               pagep, fsdata, blkdev_get_block);
 }
 
 static int blkdev_write_end(struct file *file, struct address_space *mapping,
@@ -358,12 +359,7 @@ static loff_t block_llseek(struct file *file, loff_t offset, int origin)
        return retval;
 }
        
-/*
- *     Filp is never NULL; the only case when ->fsync() is called with
- *     NULL first argument is nfsd_sync_dir() and that's not a directory.
- */
-int blkdev_fsync(struct file *filp, struct dentry *dentry, int datasync)
+int blkdev_fsync(struct file *filp, int datasync)
 {
        struct inode *bd_inode = filp->f_mapping->host;
        struct block_device *bdev = I_BDEV(bd_inode);
index e9bf864..29c2009 100644 (file)
@@ -2434,7 +2434,7 @@ void btrfs_update_iflags(struct inode *inode);
 void btrfs_inherit_iflags(struct inode *inode, struct inode *dir);
 
 /* file.c */
-int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync);
+int btrfs_sync_file(struct file *file, int datasync);
 int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
                            int skip_pinned);
 int btrfs_check_file(struct btrfs_root *root, struct inode *inode);
index 79437c5..787b50a 100644 (file)
@@ -1101,8 +1101,9 @@ int btrfs_release_file(struct inode *inode, struct file *filp)
  * important optimization for directories because holding the mutex prevents
  * new operations on the dir while we write to disk.
  */
-int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
+int btrfs_sync_file(struct file *file, int datasync)
 {
+       struct dentry *dentry = file->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        struct btrfs_root *root = BTRFS_I(inode)->root;
        int ret = 0;
index e8aa708..d54812b 100644 (file)
@@ -1949,14 +1949,11 @@ static int __block_commit_write(struct inode *inode, struct page *page,
 }
 
 /*
- * block_write_begin takes care of the basic task of block allocation and
- * bringing partial write blocks uptodate first.
- *
- * If *pagep is not NULL, then block_write_begin uses the locked page
- * at *pagep rather than allocating its own. In this case, the page will
- * not be unlocked or deallocated on failure.
+ * Filesystems implementing the new truncate sequence should use the
+ * _newtrunc postfix variant which won't incorrectly call vmtruncate.
+ * The filesystem needs to handle block truncation upon failure.
  */
-int block_write_begin(struct file *file, struct address_space *mapping,
+int block_write_begin_newtrunc(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned flags,
                        struct page **pagep, void **fsdata,
                        get_block_t *get_block)
@@ -1992,20 +1989,50 @@ int block_write_begin(struct file *file, struct address_space *mapping,
                        unlock_page(page);
                        page_cache_release(page);
                        *pagep = NULL;
-
-                       /*
-                        * prepare_write() may have instantiated a few blocks
-                        * outside i_size.  Trim these off again. Don't need
-                        * i_size_read because we hold i_mutex.
-                        */
-                       if (pos + len > inode->i_size)
-                               vmtruncate(inode, inode->i_size);
                }
        }
 
 out:
        return status;
 }
+EXPORT_SYMBOL(block_write_begin_newtrunc);
+
+/*
+ * block_write_begin takes care of the basic task of block allocation and
+ * bringing partial write blocks uptodate first.
+ *
+ * If *pagep is not NULL, then block_write_begin uses the locked page
+ * at *pagep rather than allocating its own. In this case, the page will
+ * not be unlocked or deallocated on failure.
+ */
+int block_write_begin(struct file *file, struct address_space *mapping,
+                       loff_t pos, unsigned len, unsigned flags,
+                       struct page **pagep, void **fsdata,
+                       get_block_t *get_block)
+{
+       int ret;
+
+       ret = block_write_begin_newtrunc(file, mapping, pos, len, flags,
+                                       pagep, fsdata, get_block);
+
+       /*
+        * prepare_write() may have instantiated a few blocks
+        * outside i_size.  Trim these off again. Don't need
+        * i_size_read because we hold i_mutex.
+        *
+        * Filesystems which pass down their own page also cannot
+        * call into vmtruncate here because it would lead to lock
+        * inversion problems (*pagep is locked). This is a further
+        * example of where the old truncate sequence is inadequate.
+        */
+       if (unlikely(ret) && *pagep == NULL) {
+               loff_t isize = mapping->host->i_size;
+               if (pos + len > isize)
+                       vmtruncate(mapping->host, isize);
+       }
+
+       return ret;
+}
 EXPORT_SYMBOL(block_write_begin);
 
 int block_write_end(struct file *file, struct address_space *mapping,
@@ -2324,7 +2351,7 @@ out:
  * For moronic filesystems that do not allow holes in file.
  * We may have to extend the file.
  */
-int cont_write_begin(struct file *file, struct address_space *mapping,
+int cont_write_begin_newtrunc(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned flags,
                        struct page **pagep, void **fsdata,
                        get_block_t *get_block, loff_t *bytes)
@@ -2345,11 +2372,30 @@ int cont_write_begin(struct file *file, struct address_space *mapping,
        }
 
        *pagep = NULL;
-       err = block_write_begin(file, mapping, pos, len,
+       err = block_write_begin_newtrunc(file, mapping, pos, len,
                                flags, pagep, fsdata, get_block);
 out:
        return err;
 }
+EXPORT_SYMBOL(cont_write_begin_newtrunc);
+
+int cont_write_begin(struct file *file, struct address_space *mapping,
+                       loff_t pos, unsigned len, unsigned flags,
+                       struct page **pagep, void **fsdata,
+                       get_block_t *get_block, loff_t *bytes)
+{
+       int ret;
+
+       ret = cont_write_begin_newtrunc(file, mapping, pos, len, flags,
+                                       pagep, fsdata, get_block, bytes);
+       if (unlikely(ret)) {
+               loff_t isize = mapping->host->i_size;
+               if (pos + len > isize)
+                       vmtruncate(mapping->host, isize);
+       }
+
+       return ret;
+}
 EXPORT_SYMBOL(cont_write_begin);
 
 int block_prepare_write(struct page *page, unsigned from, unsigned to,
@@ -2381,7 +2427,7 @@ EXPORT_SYMBOL(block_commit_write);
  *
  * We are not allowed to take the i_mutex here so we have to play games to
  * protect against truncate races as the page could now be beyond EOF.  Because
- * vmtruncate() writes the inode size before removing pages, once we have the
+ * truncate writes the inode size before removing pages, once we have the
  * page lock we can determine safely if the page is beyond EOF. If it is not
  * beyond EOF, then the page is guaranteed safe against truncation until we
  * unlock the page.
@@ -2464,10 +2510,11 @@ static void attach_nobh_buffers(struct page *page, struct buffer_head *head)
 }
 
 /*
- * On entry, the page is fully not uptodate.
- * On exit the page is fully uptodate in the areas outside (from,to)
+ * Filesystems implementing the new truncate sequence should use the
+ * _newtrunc postfix variant which won't incorrectly call vmtruncate.
+ * The filesystem needs to handle block truncation upon failure.
  */
-int nobh_write_begin(struct file *file, struct address_space *mapping,
+int nobh_write_begin_newtrunc(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned flags,
                        struct page **pagep, void **fsdata,
                        get_block_t *get_block)
@@ -2500,8 +2547,8 @@ int nobh_write_begin(struct file *file, struct address_space *mapping,
                unlock_page(page);
                page_cache_release(page);
                *pagep = NULL;
-               return block_write_begin(file, mapping, pos, len, flags, pagep,
-                                       fsdata, get_block);
+               return block_write_begin_newtrunc(file, mapping, pos, len,
+                                       flags, pagep, fsdata, get_block);
        }
 
        if (PageMappedToDisk(page))
@@ -2605,8 +2652,34 @@ out_release:
        page_cache_release(page);
        *pagep = NULL;
 
-       if (pos + len > inode->i_size)
-               vmtruncate(inode, inode->i_size);
+       return ret;
+}
+EXPORT_SYMBOL(nobh_write_begin_newtrunc);
+
+/*
+ * On entry, the page is fully not uptodate.
+ * On exit the page is fully uptodate in the areas outside (from,to)
+ */
+int nobh_write_begin(struct file *file, struct address_space *mapping,
+                       loff_t pos, unsigned len, unsigned flags,
+                       struct page **pagep, void **fsdata,
+                       get_block_t *get_block)
+{
+       int ret;
+
+       ret = nobh_write_begin_newtrunc(file, mapping, pos, len, flags,
+                                       pagep, fsdata, get_block);
+
+       /*
+        * prepare_write() may have instantiated a few blocks
+        * outside i_size.  Trim these off again. Don't need
+        * i_size_read because we hold i_mutex.
+        */
+       if (unlikely(ret)) {
+               loff_t isize = mapping->host->i_size;
+               if (pos + len > isize)
+                       vmtruncate(mapping->host, isize);
+       }
 
        return ret;
 }
index 0dd0b81..ae3e3a3 100644 (file)
@@ -1776,9 +1776,9 @@ out:
        spin_unlock(&ci->i_unsafe_lock);
 }
 
-int ceph_fsync(struct file *file, struct dentry *dentry, int datasync)
+int ceph_fsync(struct file *file, int datasync)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = file->f_mapping->host;
        struct ceph_inode_info *ci = ceph_inode(inode);
        unsigned flush_tid;
        int ret;
index 4fd3090..0057f4a 100644 (file)
@@ -1107,10 +1107,9 @@ static ssize_t ceph_read_dir(struct file *file, char __user *buf, size_t size,
  * an fsync() on a dir will wait for any uncommitted directory
  * operations to commit.
  */
-static int ceph_dir_fsync(struct file *file, struct dentry *dentry,
-                         int datasync)
+static int ceph_dir_fsync(struct file *file, int datasync)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        struct ceph_inode_info *ci = ceph_inode(inode);
        struct list_head *head = &ci->i_unsafe_dirops;
        struct ceph_mds_request *req;
index 3725c9e..dd1e7ad 100644 (file)
@@ -811,7 +811,7 @@ extern void ceph_put_cap(struct ceph_cap *cap);
 
 extern void ceph_queue_caps_release(struct inode *inode);
 extern int ceph_write_inode(struct inode *inode, struct writeback_control *wbc);
-extern int ceph_fsync(struct file *file, struct dentry *dentry, int datasync);
+extern int ceph_fsync(struct file *file, int datasync);
 extern void ceph_kick_flushing_caps(struct ceph_mds_client *mdsc,
                                    struct ceph_mds_session *session);
 extern int ceph_get_cap_mds(struct inode *inode);
index 0242ff9..a7eb65c 100644 (file)
@@ -84,7 +84,7 @@ extern ssize_t cifs_user_read(struct file *file, char __user *read_data,
 extern ssize_t cifs_user_write(struct file *file, const char __user *write_data,
                         size_t write_size, loff_t *poffset);
 extern int cifs_lock(struct file *, int, struct file_lock *);
-extern int cifs_fsync(struct file *, struct dentry *, int);
+extern int cifs_fsync(struct file *, int);
 extern int cifs_flush(struct file *, fl_owner_t id);
 extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
 extern const struct file_operations cifs_dir_ops;
index a83541e..f1ff785 100644 (file)
@@ -1676,7 +1676,7 @@ static int cifs_write_end(struct file *file, struct address_space *mapping,
        return rc;
 }
 
-int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
+int cifs_fsync(struct file *file, int datasync)
 {
        int xid;
        int rc = 0;
@@ -1688,7 +1688,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
        xid = GetXid();
 
        cFYI(1, "Sync file - name: %s datasync: 0x%x",
-               dentry->d_name.name, datasync);
+               file->f_path.dentry->d_name.name, datasync);
 
        rc = filemap_write_and_wait(inode->i_mapping);
        if (rc == 0) {
index d99860a..6b443ff 100644 (file)
@@ -11,8 +11,7 @@ extern int coda_fake_statfs;
 
 void coda_destroy_inodecache(void);
 int coda_init_inodecache(void);
-int coda_fsync(struct file *coda_file, struct dentry *coda_dentry,
-              int datasync);
+int coda_fsync(struct file *coda_file, int datasync);
 void coda_sysctl_init(void);
 void coda_sysctl_clean(void);
 
index 7196077..ad3cd2a 100644 (file)
@@ -202,10 +202,10 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
        return 0;
 }
 
-int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync)
+int coda_fsync(struct file *coda_file, int datasync)
 {
        struct file *host_file;
-       struct inode *coda_inode = coda_dentry->d_inode;
+       struct inode *coda_inode = coda_file->f_path.dentry->d_inode;
        struct coda_file_info *cfi;
        int err = 0;
 
index c8af2d9..4164514 100644 (file)
@@ -72,16 +72,11 @@ int configfs_setattr(struct dentry * dentry, struct iattr * iattr)
        if (!sd)
                return -EINVAL;
 
-       sd_iattr = sd->s_iattr;
-
-       error = inode_change_ok(inode, iattr);
-       if (error)
-               return error;
-
-       error = inode_setattr(inode, iattr);
+       error = simple_setattr(dentry, iattr);
        if (error)
                return error;
 
+       sd_iattr = sd->s_iattr;
        if (!sd_iattr) {
                /* setting attributes for the first time, allocate now */
                sd_iattr = kzalloc(sizeof(struct iattr), GFP_KERNEL);
index da111aa..7600aac 100644 (file)
@@ -1134,27 +1134,8 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
        return ret;
 }
 
-/*
- * This is a library function for use by filesystem drivers.
- *
- * The locking rules are governed by the flags parameter:
- *  - if the flags value contains DIO_LOCKING we use a fancy locking
- *    scheme for dumb filesystems.
- *    For writes this function is called under i_mutex and returns with
- *    i_mutex held, for reads, i_mutex is not held on entry, but it is
- *    taken and dropped again before returning.
- *    For reads and writes i_alloc_sem is taken in shared mode and released
- *    on I/O completion (which may happen asynchronously after returning to
- *    the caller).
- *
- *  - if the flags value does NOT contain DIO_LOCKING we don't use any
- *    internal locking but rather rely on the filesystem to synchronize
- *    direct I/O reads/writes versus each other and truncate.
- *    For reads and writes both i_mutex and i_alloc_sem are not held on
- *    entry and are never taken.
- */
 ssize_t
-__blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
+__blockdev_direct_IO_newtrunc(int rw, struct kiocb *iocb, struct inode *inode,
        struct block_device *bdev, const struct iovec *iov, loff_t offset, 
        unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io,
        dio_submit_t submit_io, int flags)
@@ -1247,9 +1228,46 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
                                nr_segs, blkbits, get_block, end_io,
                                submit_io, dio);
 
+out:
+       return retval;
+}
+EXPORT_SYMBOL(__blockdev_direct_IO_newtrunc);
+
+/*
+ * This is a library function for use by filesystem drivers.
+ *
+ * The locking rules are governed by the flags parameter:
+ *  - if the flags value contains DIO_LOCKING we use a fancy locking
+ *    scheme for dumb filesystems.
+ *    For writes this function is called under i_mutex and returns with
+ *    i_mutex held, for reads, i_mutex is not held on entry, but it is
+ *    taken and dropped again before returning.
+ *    For reads and writes i_alloc_sem is taken in shared mode and released
+ *    on I/O completion (which may happen asynchronously after returning to
+ *    the caller).
+ *
+ *  - if the flags value does NOT contain DIO_LOCKING we don't use any
+ *    internal locking but rather rely on the filesystem to synchronize
+ *    direct I/O reads/writes versus each other and truncate.
+ *    For reads and writes both i_mutex and i_alloc_sem are not held on
+ *    entry and are never taken.
+ */
+ssize_t
+__blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
+       struct block_device *bdev, const struct iovec *iov, loff_t offset,
+       unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io,
+       dio_submit_t submit_io, int flags)
+{
+       ssize_t retval;
+
+       retval = __blockdev_direct_IO_newtrunc(rw, iocb, inode, bdev, iov,
+                       offset, nr_segs, get_block, end_io, submit_io, flags);
        /*
         * In case of error extending write may have instantiated a few
         * blocks outside i_size. Trim these off again for DIO_LOCKING.
+        * NOTE: DIO_NO_LOCK/DIO_OWN_LOCK callers have to handle this in
+        * their own manner. This is a further example of where the old
+        * truncate sequence is inadequate.
         *
         * NOTE: filesystems with their own locking have to handle this
         * on their own.
@@ -1257,12 +1275,13 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
        if (flags & DIO_LOCKING) {
                if (unlikely((rw & WRITE) && retval < 0)) {
                        loff_t isize = i_size_read(inode);
+                       loff_t end = offset + iov_length(iov, nr_segs);
+
                        if (end > isize)
                                vmtruncate(inode, isize);
                }
        }
 
-out:
        return retval;
 }
 EXPORT_SYMBOL(__blockdev_direct_IO);
index 3bdddbc..e8fcf4e 100644 (file)
@@ -274,7 +274,7 @@ static int ecryptfs_release(struct inode *inode, struct file *file)
 }
 
 static int
-ecryptfs_fsync(struct file *file, struct dentry *dentry, int datasync)
+ecryptfs_fsync(struct file *file, int datasync)
 {
        return vfs_fsync(ecryptfs_file_to_lower(file), datasync);
 }
index 65dee2f..31ef525 100644 (file)
@@ -805,7 +805,7 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,
                                    - (ia->ia_size & ~PAGE_CACHE_MASK));
 
                if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
-                       rc = vmtruncate(inode, ia->ia_size);
+                       rc = simple_setsize(inode, ia->ia_size);
                        if (rc)
                                goto out;
                        lower_ia->ia_size = ia->ia_size;
@@ -830,7 +830,7 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,
                                goto out;
                        }
                }
-               vmtruncate(inode, ia->ia_size);
+               simple_setsize(inode, ia->ia_size);
                rc = ecryptfs_write_inode_size_to_metadata(inode);
                if (rc) {
                        printk(KERN_ERR "Problem with "
index 839b9dc..fef6899 100644 (file)
@@ -40,12 +40,11 @@ static int exofs_release_file(struct inode *inode, struct file *filp)
        return 0;
 }
 
-static int exofs_file_fsync(struct file *filp, struct dentry *dentry,
-                           int datasync)
+static int exofs_file_fsync(struct file *filp, int datasync)
 {
        int ret;
        struct address_space *mapping = filp->f_mapping;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = mapping->host;
        struct super_block *sb;
 
        ret = filemap_write_and_wait(mapping);
@@ -66,7 +65,7 @@ static int exofs_file_fsync(struct file *filp, struct dentry *dentry,
 
 static int exofs_flush(struct file *file, fl_owner_t id)
 {
-       exofs_file_fsync(file, file->f_path.dentry, 1);
+       exofs_file_fsync(file, 1);
        /* TODO: Flush the OSD target */
        return 0;
 }
index 0b038e4..52b34f1 100644 (file)
@@ -122,7 +122,6 @@ extern int ext2_write_inode (struct inode *, struct writeback_control *);
 extern void ext2_delete_inode (struct inode *);
 extern int ext2_sync_inode (struct inode *);
 extern int ext2_get_block(struct inode *, sector_t, struct buffer_head *, int);
-extern void ext2_truncate (struct inode *);
 extern int ext2_setattr (struct dentry *, struct iattr *);
 extern void ext2_set_inode_flags(struct inode *inode);
 extern void ext2_get_inode_flags(struct ext2_inode_info *);
@@ -155,7 +154,7 @@ extern void ext2_write_super (struct super_block *);
 extern const struct file_operations ext2_dir_operations;
 
 /* file.c */
-extern int ext2_fsync(struct file *file, struct dentry *dentry, int datasync);
+extern int ext2_fsync(struct file *file, int datasync);
 extern const struct inode_operations ext2_file_inode_operations;
 extern const struct file_operations ext2_file_operations;
 extern const struct file_operations ext2_xip_file_operations;
index 5d198d0..49eec94 100644 (file)
@@ -40,13 +40,13 @@ static int ext2_release_file (struct inode * inode, struct file * filp)
        return 0;
 }
 
-int ext2_fsync(struct file *file, struct dentry *dentry, int datasync)
+int ext2_fsync(struct file *file, int datasync)
 {
        int ret;
-       struct super_block *sb = dentry->d_inode->i_sb;
+       struct super_block *sb = file->f_mapping->host->i_sb;
        struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
 
-       ret = simple_fsync(file, dentry, datasync);
+       ret = generic_file_fsync(file, datasync);
        if (ret == -EIO || test_and_clear_bit(AS_EIO, &mapping->flags)) {
                /* We don't really know where the IO error happened... */
                ext2_error(sb, __func__,
@@ -95,7 +95,6 @@ const struct file_operations ext2_xip_file_operations = {
 #endif
 
 const struct inode_operations ext2_file_inode_operations = {
-       .truncate       = ext2_truncate,
 #ifdef CONFIG_EXT2_FS_XATTR
        .setxattr       = generic_setxattr,
        .getxattr       = generic_getxattr,
index 527c46d..1921443 100644 (file)
@@ -54,6 +54,18 @@ static inline int ext2_inode_is_fast_symlink(struct inode *inode)
                inode->i_blocks - ea_blocks == 0);
 }
 
+static void ext2_truncate_blocks(struct inode *inode, loff_t offset);
+
+static void ext2_write_failed(struct address_space *mapping, loff_t to)
+{
+       struct inode *inode = mapping->host;
+
+       if (to > inode->i_size) {
+               truncate_pagecache(inode, to, inode->i_size);
+               ext2_truncate_blocks(inode, inode->i_size);
+       }
+}
+
 /*
  * Called at the last iput() if i_nlink is zero.
  */
@@ -71,7 +83,7 @@ void ext2_delete_inode (struct inode * inode)
 
        inode->i_size = 0;
        if (inode->i_blocks)
-               ext2_truncate (inode);
+               ext2_truncate_blocks(inode, 0);
        ext2_free_inode (inode);
 
        return;
@@ -757,8 +769,8 @@ int __ext2_write_begin(struct file *file, struct address_space *mapping,
                loff_t pos, unsigned len, unsigned flags,
                struct page **pagep, void **fsdata)
 {
-       return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
-                                                       ext2_get_block);
+       return block_write_begin_newtrunc(file, mapping, pos, len, flags,
+                                       pagep, fsdata, ext2_get_block);
 }
 
 static int
@@ -766,8 +778,25 @@ ext2_write_begin(struct file *file, struct address_space *mapping,
                loff_t pos, unsigned len, unsigned flags,
                struct page **pagep, void **fsdata)
 {
+       int ret;
+
        *pagep = NULL;
-       return __ext2_write_begin(file, mapping, pos, len, flags, pagep,fsdata);
+       ret = __ext2_write_begin(file, mapping, pos, len, flags, pagep, fsdata);
+       if (ret < 0)
+               ext2_write_failed(mapping, pos + len);
+       return ret;
+}
+
+static int ext2_write_end(struct file *file, struct address_space *mapping,
+                       loff_t pos, unsigned len, unsigned copied,
+                       struct page *page, void *fsdata)
+{
+       int ret;
+
+       ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
+       if (ret < len)
+               ext2_write_failed(mapping, pos + len);
+       return ret;
 }
 
 static int
@@ -775,13 +804,18 @@ ext2_nobh_write_begin(struct file *file, struct address_space *mapping,
                loff_t pos, unsigned len, unsigned flags,
                struct page **pagep, void **fsdata)
 {
+       int ret;
+
        /*
         * Dir-in-pagecache still uses ext2_write_begin. Would have to rework
         * directory handling code to pass around offsets rather than struct
         * pages in order to make this work easily.
         */
-       return nobh_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
-                                                       ext2_get_block);
+       ret = nobh_write_begin_newtrunc(file, mapping, pos, len, flags, pagep,
+                                               fsdata, ext2_get_block);
+       if (ret < 0)
+               ext2_write_failed(mapping, pos + len);
+       return ret;
 }
 
 static int ext2_nobh_writepage(struct page *page,
@@ -800,10 +834,15 @@ ext2_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
                        loff_t offset, unsigned long nr_segs)
 {
        struct file *file = iocb->ki_filp;
-       struct inode *inode = file->f_mapping->host;
-
-       return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
-                               offset, nr_segs, ext2_get_block, NULL);
+       struct address_space *mapping = file->f_mapping;
+       struct inode *inode = mapping->host;
+       ssize_t ret;
+
+       ret = blockdev_direct_IO_newtrunc(rw, iocb, inode, inode->i_sb->s_bdev,
+                               iov, offset, nr_segs, ext2_get_block, NULL);
+       if (ret < 0 && (rw & WRITE))
+               ext2_write_failed(mapping, offset + iov_length(iov, nr_segs));
+       return ret;
 }
 
 static int
@@ -818,7 +857,7 @@ const struct address_space_operations ext2_aops = {
        .writepage              = ext2_writepage,
        .sync_page              = block_sync_page,
        .write_begin            = ext2_write_begin,
-       .write_end              = generic_write_end,
+       .write_end              = ext2_write_end,
        .bmap                   = ext2_bmap,
        .direct_IO              = ext2_direct_IO,
        .writepages             = ext2_writepages,
@@ -1027,7 +1066,7 @@ static void ext2_free_branches(struct inode *inode, __le32 *p, __le32 *q, int de
                ext2_free_data(inode, p, q);
 }
 
-void ext2_truncate(struct inode *inode)
+static void __ext2_truncate_blocks(struct inode *inode, loff_t offset)
 {
        __le32 *i_data = EXT2_I(inode)->i_data;
        struct ext2_inode_info *ei = EXT2_I(inode);
@@ -1039,27 +1078,8 @@ void ext2_truncate(struct inode *inode)
        int n;
        long iblock;
        unsigned blocksize;
-
-       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;
-
        blocksize = inode->i_sb->s_blocksize;
-       iblock = (inode->i_size + blocksize-1)
-                                       >> EXT2_BLOCK_SIZE_BITS(inode->i_sb);
-
-       if (mapping_is_xip(inode->i_mapping))
-               xip_truncate_page(inode->i_mapping, inode->i_size);
-       else if (test_opt(inode->i_sb, NOBH))
-               nobh_truncate_page(inode->i_mapping,
-                               inode->i_size, ext2_get_block);
-       else
-               block_truncate_page(inode->i_mapping,
-                               inode->i_size, ext2_get_block);
+       iblock = (offset + blocksize-1) >> EXT2_BLOCK_SIZE_BITS(inode->i_sb);
 
        n = ext2_block_to_path(inode, iblock, offsets, NULL);
        if (n == 0)
@@ -1127,6 +1147,62 @@ do_indirects:
        ext2_discard_reservation(inode);
 
        mutex_unlock(&ei->truncate_mutex);
+}
+
+static void ext2_truncate_blocks(struct inode *inode, loff_t offset)
+{
+       /*
+        * XXX: it seems like a bug here that we don't allow
+        * IS_APPEND inode to have blocks-past-i_size trimmed off.
+        * review and fix this.
+        *
+        * Also would be nice to be able to handle IO errors and such,
+        * but that's probably too much to ask.
+        */
+       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;
+       __ext2_truncate_blocks(inode, offset);
+}
+
+int ext2_setsize(struct inode *inode, loff_t newsize)
+{
+       loff_t oldsize;
+       int error;
+
+       error = inode_newsize_ok(inode, newsize);
+       if (error)
+               return error;
+
+       if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+           S_ISLNK(inode->i_mode)))
+               return -EINVAL;
+       if (ext2_inode_is_fast_symlink(inode))
+               return -EINVAL;
+       if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+               return -EPERM;
+
+       if (mapping_is_xip(inode->i_mapping))
+               error = xip_truncate_page(inode->i_mapping, newsize);
+       else if (test_opt(inode->i_sb, NOBH))
+               error = nobh_truncate_page(inode->i_mapping,
+                               newsize, ext2_get_block);
+       else
+               error = block_truncate_page(inode->i_mapping,
+                               newsize, ext2_get_block);
+       if (error)
+               return error;
+
+       oldsize = inode->i_size;
+       i_size_write(inode, newsize);
+       truncate_pagecache(inode, oldsize, newsize);
+
+       __ext2_truncate_blocks(inode, newsize);
+
        inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
        if (inode_needs_sync(inode)) {
                sync_mapping_buffers(inode->i_mapping);
@@ -1134,6 +1210,8 @@ do_indirects:
        } else {
                mark_inode_dirty(inode);
        }
+
+       return 0;
 }
 
 static struct ext2_inode *ext2_get_inode(struct super_block *sb, ino_t ino,
@@ -1474,8 +1552,15 @@ int ext2_setattr(struct dentry *dentry, struct iattr *iattr)
                if (error)
                        return error;
        }
-       error = inode_setattr(inode, iattr);
-       if (!error && (iattr->ia_valid & ATTR_MODE))
+       if (iattr->ia_valid & ATTR_SIZE) {
+               error = ext2_setsize(inode, iattr->ia_size);
+               if (error)
+                       return error;
+       }
+       generic_setattr(inode, iattr);
+       if (iattr->ia_valid & ATTR_MODE)
                error = ext2_acl_chmod(inode);
+       mark_inode_dirty(inode);
+
        return error;
 }
index fcf7487..d7e9f74 100644 (file)
@@ -43,9 +43,9 @@
  * inode to disk.
  */
 
-int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync)
+int ext3_sync_file(struct file *file, int datasync)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = file->f_mapping->host;
        struct ext3_inode_info *ei = EXT3_I(inode);
        journal_t *journal = EXT3_SB(inode->i_sb)->s_journal;
        int ret, needs_barrier = 0;
index 60bd310..19a4de5 100644 (file)
@@ -1519,7 +1519,7 @@ extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
 extern void ext4_htree_free_dir_info(struct dir_private_info *p);
 
 /* fsync.c */
-extern int ext4_sync_file(struct file *, struct dentry *, int);
+extern int ext4_sync_file(struct file *, int);
 
 /* hash.c */
 extern int ext4fs_dirhash(const char *name, int len, struct
index b6a74f9..592adf2 100644 (file)
@@ -71,9 +71,9 @@ static void ext4_sync_parent(struct inode *inode)
  * i_mutex lock is held when entering and exiting this function
  */
 
-int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync)
+int ext4_sync_file(struct file *file, int datasync)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = file->f_mapping->host;
        struct ext4_inode_info *ei = EXT4_I(inode);
        journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
        int ret;
@@ -81,7 +81,7 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync)
 
        J_ASSERT(ext4_journal_current_handle() == NULL);
 
-       trace_ext4_sync_file(file, dentry, datasync);
+       trace_ext4_sync_file(file, datasync);
 
        if (inode->i_sb->s_flags & MS_RDONLY)
                return 0;
@@ -91,7 +91,7 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync)
                return ret;
 
        if (!journal) {
-               ret = simple_fsync(file, dentry, datasync);
+               ret = generic_file_fsync(file, datasync);
                if (!ret && !list_empty(&inode->i_dentry))
                        ext4_sync_parent(inode);
                return ret;
index 53dba57..27ac257 100644 (file)
@@ -306,11 +306,11 @@ extern long fat_generic_ioctl(struct file *filp, unsigned int cmd,
 extern const struct file_operations fat_file_operations;
 extern const struct inode_operations fat_file_inode_operations;
 extern int fat_setattr(struct dentry * dentry, struct iattr * attr);
-extern void fat_truncate(struct inode *inode);
+extern int fat_setsize(struct inode *inode, loff_t offset);
+extern void fat_truncate_blocks(struct inode *inode, loff_t offset);
 extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry,
                       struct kstat *stat);
-extern int fat_file_fsync(struct file *file, struct dentry *dentry,
-                         int datasync);
+extern int fat_file_fsync(struct file *file, int datasync);
 
 /* fat/inode.c */
 extern void fat_attach(struct inode *inode, loff_t i_pos);
index a14c2f6..990dfae 100644 (file)
@@ -149,12 +149,12 @@ static int fat_file_release(struct inode *inode, struct file *filp)
        return 0;
 }
 
-int fat_file_fsync(struct file *filp, struct dentry *dentry, int datasync)
+int fat_file_fsync(struct file *filp, int datasync)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = filp->f_mapping->host;
        int res, err;
 
-       res = simple_fsync(filp, dentry, datasync);
+       res = generic_file_fsync(filp, datasync);
        err = sync_mapping_buffers(MSDOS_SB(inode->i_sb)->fat_inode->i_mapping);
 
        return res ? res : err;
@@ -283,7 +283,7 @@ static int fat_free(struct inode *inode, int skip)
        return fat_free_clusters(inode, free_start);
 }
 
-void fat_truncate(struct inode *inode)
+void fat_truncate_blocks(struct inode *inode, loff_t offset)
 {
        struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
        const unsigned int cluster_size = sbi->cluster_size;
@@ -293,10 +293,10 @@ void fat_truncate(struct inode *inode)
         * This protects against truncating a file bigger than it was then
         * trying to write into the hole.
         */
-       if (MSDOS_I(inode)->mmu_private > inode->i_size)
-               MSDOS_I(inode)->mmu_private = inode->i_size;
+       if (MSDOS_I(inode)->mmu_private > offset)
+               MSDOS_I(inode)->mmu_private = offset;
 
-       nr_clusters = (inode->i_size + (cluster_size - 1)) >> sbi->cluster_bits;
+       nr_clusters = (offset + (cluster_size - 1)) >> sbi->cluster_bits;
 
        fat_free(inode, nr_clusters);
        fat_flush_inodes(inode->i_sb, inode, NULL);
@@ -364,6 +364,18 @@ static int fat_allow_set_time(struct msdos_sb_info *sbi, struct inode *inode)
        return 0;
 }
 
+int fat_setsize(struct inode *inode, loff_t offset)
+{
+       int error;
+
+       error = simple_setsize(inode, offset);
+       if (error)
+               return error;
+       fat_truncate_blocks(inode, offset);
+
+       return error;
+}
+
 #define TIMES_SET_FLAGS        (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)
 /* valid file mode bits */
 #define FAT_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXUGO)
@@ -378,7 +390,8 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
        /*
         * Expand the file. Since inode_setattr() updates ->i_size
         * before calling the ->truncate(), but FAT needs to fill the
-        * hole before it.
+        * hole before it. XXX: this is no longer true with new truncate
+        * sequence.
         */
        if (attr->ia_valid & ATTR_SIZE) {
                if (attr->ia_size > inode->i_size) {
@@ -427,15 +440,20 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
                        attr->ia_valid &= ~ATTR_MODE;
        }
 
-       if (attr->ia_valid)
-               error = inode_setattr(inode, attr);
+       if (attr->ia_valid & ATTR_SIZE) {
+               error = fat_setsize(inode, attr->ia_size);
+               if (error)
+                       goto out;
+       }
+
+       generic_setattr(inode, attr);
+       mark_inode_dirty(inode);
 out:
        return error;
 }
 EXPORT_SYMBOL_GPL(fat_setattr);
 
 const struct inode_operations fat_file_inode_operations = {
-       .truncate       = fat_truncate,
        .setattr        = fat_setattr,
        .getattr        = fat_getattr,
 };
index ed33904..7bf45ae 100644 (file)
@@ -142,14 +142,29 @@ static int fat_readpages(struct file *file, struct address_space *mapping,
        return mpage_readpages(mapping, pages, nr_pages, fat_get_block);
 }
 
+static void fat_write_failed(struct address_space *mapping, loff_t to)
+{
+       struct inode *inode = mapping->host;
+
+       if (to > inode->i_size) {
+               truncate_pagecache(inode, to, inode->i_size);
+               fat_truncate_blocks(inode, inode->i_size);
+       }
+}
+
 static int fat_write_begin(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned flags,
                        struct page **pagep, void **fsdata)
 {
+       int err;
+
        *pagep = NULL;
-       return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
-                               fat_get_block,
+       err = cont_write_begin_newtrunc(file, mapping, pos, len, flags,
+                               pagep, fsdata, fat_get_block,
                                &MSDOS_I(mapping->host)->mmu_private);
+       if (err < 0)
+               fat_write_failed(mapping, pos + len);
+       return err;
 }
 
 static int fat_write_end(struct file *file, struct address_space *mapping,
@@ -159,6 +174,8 @@ static int fat_write_end(struct file *file, struct address_space *mapping,
        struct inode *inode = mapping->host;
        int err;
        err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata);
+       if (err < len)
+               fat_write_failed(mapping, pos + len);
        if (!(err < 0) && !(MSDOS_I(inode)->i_attrs & ATTR_ARCH)) {
                inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
                MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
@@ -172,7 +189,9 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb,
                             loff_t offset, unsigned long nr_segs)
 {
        struct file *file = iocb->ki_filp;
-       struct inode *inode = file->f_mapping->host;
+       struct address_space *mapping = file->f_mapping;
+       struct inode *inode = mapping->host;
+       ssize_t ret;
 
        if (rw == WRITE) {
                /*
@@ -193,8 +212,12 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb,
         * FAT need to use the DIO_LOCKING for avoiding the race
         * condition of fat_get_block() and ->truncate().
         */
-       return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
-                                 offset, nr_segs, fat_get_block, NULL);
+       ret = blockdev_direct_IO_newtrunc(rw, iocb, inode, inode->i_sb->s_bdev,
+                               iov, offset, nr_segs, fat_get_block, NULL);
+       if (ret < 0 && (rw & WRITE))
+               fat_write_failed(mapping, offset + iov_length(iov, nr_segs));
+
+       return ret;
 }
 
 static sector_t _fat_bmap(struct address_space *mapping, sector_t block)
@@ -429,7 +452,7 @@ static void fat_delete_inode(struct inode *inode)
 {
        truncate_inode_pages(&inode->i_data, 0);
        inode->i_size = 0;
-       fat_truncate(inode);
+       fat_truncate_blocks(inode, 0);
        clear_inode(inode);
 }
 
index 32d12b7..5c7d10e 100644 (file)
@@ -194,14 +194,6 @@ struct file *alloc_file(struct path *path, fmode_t mode,
 }
 EXPORT_SYMBOL(alloc_file);
 
-void fput(struct file *file)
-{
-       if (atomic_long_dec_and_test(&file->f_count))
-               __fput(file);
-}
-
-EXPORT_SYMBOL(fput);
-
 /**
  * drop_file_write_access - give up ability to write to a file
  * @file: the file to which we will stop writing
@@ -227,10 +219,9 @@ void drop_file_write_access(struct file *file)
 }
 EXPORT_SYMBOL_GPL(drop_file_write_access);
 
-/* __fput is called from task context when aio completion releases the last
- * last use of a struct file *.  Do not use otherwise.
+/* the real guts of fput() - releasing the last reference to file
  */
-void __fput(struct file *file)
+static void __fput(struct file *file)
 {
        struct dentry *dentry = file->f_path.dentry;
        struct vfsmount *mnt = file->f_path.mnt;
@@ -268,6 +259,14 @@ void __fput(struct file *file)
        mntput(mnt);
 }
 
+void fput(struct file *file)
+{
+       if (atomic_long_dec_and_test(&file->f_count))
+               __fput(file);
+}
+
+EXPORT_SYMBOL(fput);
+
 struct file *fget(unsigned int fd)
 {
        struct file *file;
index 4787ae6..3cdc5f7 100644 (file)
@@ -1156,10 +1156,9 @@ static int fuse_dir_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync)
+static int fuse_dir_fsync(struct file *file, int datasync)
 {
-       /* nfsd can call this with no file */
-       return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
+       return fuse_fsync_common(file, datasync, 1);
 }
 
 static bool update_mtime(unsigned ivalid)
index a9f5e13..b5fd6f9 100644 (file)
@@ -351,10 +351,9 @@ static void fuse_sync_writes(struct inode *inode)
        fuse_release_nowrite(inode);
 }
 
-int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
-                     int isdir)
+int fuse_fsync_common(struct file *file, int datasync, int isdir)
 {
-       struct inode *inode = de->d_inode;
+       struct inode *inode = file->f_mapping->host;
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_file *ff = file->private_data;
        struct fuse_req *req;
@@ -403,9 +402,9 @@ int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
        return err;
 }
 
-static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
+static int fuse_fsync(struct file *file, int datasync)
 {
-       return fuse_fsync_common(file, de, datasync, 0);
+       return fuse_fsync_common(file, datasync, 0);
 }
 
 void fuse_read_fill(struct fuse_req *req, struct file *file, loff_t pos,
index 01cc462..2c0d14a 100644 (file)
@@ -568,8 +568,7 @@ void fuse_release_common(struct file *file, int opcode);
 /**
  * Send FSYNC or FSYNCDIR request
  */
-int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
-                     int isdir);
+int fuse_fsync_common(struct file *file, int datasync, int isdir);
 
 /**
  * Notify poll wakeup
index a739a0a..9f8b525 100644 (file)
@@ -700,8 +700,14 @@ out:
                return 0;
 
        page_cache_release(page);
+
+       /*
+        * XXX(hch): the call below should probably be replaced with
+        * a call to the gfs2-specific truncate blocks helper to actually
+        * release disk blocks..
+        */
        if (pos + len > ip->i_inode.i_size)
-               vmtruncate(&ip->i_inode, ip->i_inode.i_size);
+               simple_setsize(&ip->i_inode, ip->i_inode.i_size);
 out_endtrans:
        gfs2_trans_end(sdp);
 out_trans_fail:
index b20bfcc..ed9a94f 100644 (file)
@@ -554,9 +554,9 @@ static int gfs2_close(struct inode *inode, struct file *file)
  * Returns: errno
  */
 
-static int gfs2_fsync(struct file *file, struct dentry *dentry, int datasync)
+static int gfs2_fsync(struct file *file, int datasync)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = file->f_mapping->host;
        int sync_state = inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC);
        int ret = 0;
 
index 4e64352..98cdd05 100644 (file)
@@ -1071,6 +1071,9 @@ int gfs2_permission(struct inode *inode, int mask)
        return error;
 }
 
+/*
+ * XXX: should be changed to have proper ordering by opencoding simple_setsize
+ */
 static int setattr_size(struct inode *inode, struct iattr *attr)
 {
        struct gfs2_inode *ip = GFS2_I(inode);
@@ -1081,7 +1084,7 @@ static int setattr_size(struct inode *inode, struct iattr *attr)
                error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks);
                if (error)
                        return error;
-               error = vmtruncate(inode, attr->ia_size);
+               error = simple_setsize(inode, attr->ia_size);
                gfs2_trans_end(sdp);
                if (error) 
                        return error;
index 3a029d8..87ac189 100644 (file)
@@ -411,9 +411,9 @@ int hostfs_file_open(struct inode *ino, struct file *file)
        return 0;
 }
 
-int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync)
+int hostfs_fsync(struct file *file, int datasync)
 {
-       return fsync_file(HOSTFS_I(dentry->d_inode)->fd, datasync);
+       return fsync_file(HOSTFS_I(file->f_mapping->host)->fd, datasync);
 }
 
 static const struct file_operations hostfs_file_fops = {
index 3efabff..a9ae9bf 100644 (file)
@@ -19,9 +19,9 @@ static int hpfs_file_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-int hpfs_file_fsync(struct file *file, struct dentry *dentry, int datasync)
+int hpfs_file_fsync(struct file *file, int datasync)
 {
-       /*return file_fsync(file, dentry);*/
+       /*return file_fsync(file, datasync);*/
        return 0; /* Don't fsync :-) */
 }
 
index 97bf738..75f9d43 100644 (file)
@@ -268,7 +268,7 @@ void hpfs_set_ea(struct inode *, struct fnode *, const char *,
 
 /* file.c */
 
-int hpfs_file_fsync(struct file *, struct dentry *, int);
+int hpfs_file_fsync(struct file *, int);
 extern const struct file_operations hpfs_file_ops;
 extern const struct inode_operations hpfs_file_iops;
 extern const struct address_space_operations hpfs_aops;
index 2e4dfa8..826c3f9 100644 (file)
@@ -587,7 +587,7 @@ static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir)
        return err;
 }
 
-static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync)
+static int hppfs_fsync(struct file *file, int datasync)
 {
        return 0;
 }
index a0bbd3d..a4e9a7e 100644 (file)
@@ -688,7 +688,7 @@ static void init_once(void *foo)
 const struct file_operations hugetlbfs_file_operations = {
        .read                   = hugetlbfs_read,
        .mmap                   = hugetlbfs_file_mmap,
-       .fsync                  = simple_sync_file,
+       .fsync                  = noop_fsync,
        .get_unmapped_area      = hugetlb_get_unmapped_area,
 };
 
index e7291c1..8134970 100644 (file)
@@ -26,9 +26,9 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
                        struct page **pagep, void **fsdata);
 static int jffs2_readpage (struct file *filp, struct page *pg);
 
-int jffs2_fsync(struct file *filp, struct dentry *dentry, int datasync)
+int jffs2_fsync(struct file *filp, int datasync)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = filp->f_mapping->host;
        struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
 
        /* Trigger GC to flush any pending writes for this inode */
index 86e0821..8bc2c80 100644 (file)
@@ -169,13 +169,13 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
        mutex_unlock(&f->sem);
        jffs2_complete_reservation(c);
 
-       /* We have to do the vmtruncate() without f->sem held, since
+       /* We have to do the simple_setsize() without f->sem held, since
           some pages may be locked and waiting for it in readpage().
           We are protected from a simultaneous write() extending i_size
           back past iattr->ia_size, because do_truncate() holds the
           generic inode semaphore. */
        if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) {
-               vmtruncate(inode, iattr->ia_size);      
+               simple_setsize(inode, iattr->ia_size);
                inode->i_blocks = (inode->i_size + 511) >> 9;
        }       
 
index 035a767..4791aac 100644 (file)
@@ -158,7 +158,7 @@ extern const struct inode_operations jffs2_dir_inode_operations;
 extern const struct file_operations jffs2_file_operations;
 extern const struct inode_operations jffs2_file_inode_operations;
 extern const struct address_space_operations jffs2_file_address_operations;
-int jffs2_fsync(struct file *, struct dentry *, int);
+int jffs2_fsync(struct file *, int);
 int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg);
 
 /* ioctl.c */
index 85d9ec6..127263c 100644 (file)
@@ -27,9 +27,9 @@
 #include "jfs_acl.h"
 #include "jfs_debug.h"
 
-int jfs_fsync(struct file *file, struct dentry *dentry, int datasync)
+int jfs_fsync(struct file *file, int datasync)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = file->f_mapping->host;
        int rc = 0;
 
        if (!(inode->i_state & I_DIRTY) ||
index 9e6bda3..11042b1 100644 (file)
@@ -21,7 +21,7 @@
 struct fid;
 
 extern struct inode *ialloc(struct inode *, umode_t);
-extern int jfs_fsync(struct file *, struct dentry *, int);
+extern int jfs_fsync(struct file *, int);
 extern long jfs_ioctl(struct file *, unsigned int, unsigned long);
 extern long jfs_compat_ioctl(struct file *, unsigned int, unsigned long);
 extern struct inode *jfs_iget(struct super_block *, unsigned long);
index 232bea4..09e1016 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/slab.h>
 #include <linux/mount.h>
 #include <linux/vfs.h>
+#include <linux/quotaops.h>
 #include <linux/mutex.h>
 #include <linux/exportfs.h>
 #include <linux/writeback.h>
@@ -58,11 +59,6 @@ struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, struct na
        return NULL;
 }
 
-int simple_sync_file(struct file * file, struct dentry *dentry, int datasync)
-{
-       return 0;
-}
 int dcache_dir_open(struct inode *inode, struct file *file)
 {
        static struct qstr cursor_name = {.len = 1, .name = "."};
@@ -190,7 +186,7 @@ const struct file_operations simple_dir_operations = {
        .llseek         = dcache_dir_lseek,
        .read           = generic_read_dir,
        .readdir        = dcache_readdir,
-       .fsync          = simple_sync_file,
+       .fsync          = noop_fsync,
 };
 
 const struct inode_operations simple_dir_inode_operations = {
@@ -330,6 +326,81 @@ int simple_rename(struct inode *old_dir, struct dentry *old_dentry,
        return 0;
 }
 
+/**
+ * simple_setsize - handle core mm and vfs requirements for file size change
+ * @inode: inode
+ * @newsize: new file size
+ *
+ * Returns 0 on success, -error on failure.
+ *
+ * simple_setsize must be called with inode_mutex held.
+ *
+ * simple_setsize will check that the requested new size is OK (see
+ * inode_newsize_ok), and then will perform the necessary i_size update
+ * and pagecache truncation (if necessary). It will be typically be called
+ * from the filesystem's setattr function when ATTR_SIZE is passed in.
+ *
+ * The inode itself must have correct permissions and attributes to allow
+ * i_size to be changed, this function then just checks that the new size
+ * requested is valid.
+ *
+ * In the case of simple in-memory filesystems with inodes stored solely
+ * in the inode cache, and file data in the pagecache, nothing more needs
+ * to be done to satisfy a truncate request. Filesystems with on-disk
+ * blocks for example will need to free them in the case of truncate, in
+ * that case it may be easier not to use simple_setsize (but each of its
+ * components will likely be required at some point to update pagecache
+ * and inode etc).
+ */
+int simple_setsize(struct inode *inode, loff_t newsize)
+{
+       loff_t oldsize;
+       int error;
+
+       error = inode_newsize_ok(inode, newsize);
+       if (error)
+               return error;
+
+       oldsize = inode->i_size;
+       i_size_write(inode, newsize);
+       truncate_pagecache(inode, oldsize, newsize);
+
+       return error;
+}
+EXPORT_SYMBOL(simple_setsize);
+
+/**
+ * simple_setattr - setattr for simple in-memory filesystem
+ * @dentry: dentry
+ * @iattr: iattr structure
+ *
+ * Returns 0 on success, -error on failure.
+ *
+ * simple_setattr implements setattr for an in-memory filesystem which
+ * does not store its own file data or metadata (eg. uses the page cache
+ * and inode cache as its data store).
+ */
+int simple_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+       struct inode *inode = dentry->d_inode;
+       int error;
+
+       error = inode_change_ok(inode, iattr);
+       if (error)
+               return error;
+
+       if (iattr->ia_valid & ATTR_SIZE) {
+               error = simple_setsize(inode, iattr->ia_size);
+               if (error)
+                       return error;
+       }
+
+       generic_setattr(inode, iattr);
+
+       return error;
+}
+EXPORT_SYMBOL(simple_setattr);
+
 int simple_readpage(struct file *file, struct page *page)
 {
        clear_highpage(page);
@@ -851,13 +922,22 @@ struct dentry *generic_fh_to_parent(struct super_block *sb, struct fid *fid,
 }
 EXPORT_SYMBOL_GPL(generic_fh_to_parent);
 
-int simple_fsync(struct file *file, struct dentry *dentry, int datasync)
+/**
+ * generic_file_fsync - generic fsync implementation for simple filesystems
+ * @file:      file to synchronize
+ * @datasync:  only synchronize essential metadata if true
+ *
+ * This is a generic implementation of the fsync method for simple
+ * filesystems which track all non-inode metadata in the buffers list
+ * hanging off the address_space structure.
+ */
+int generic_file_fsync(struct file *file, int datasync)
 {
        struct writeback_control wbc = {
                .sync_mode = WB_SYNC_ALL,
                .nr_to_write = 0, /* metadata-only; caller takes care of data */
        };
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = file->f_mapping->host;
        int err;
        int ret;
 
@@ -872,7 +952,15 @@ int simple_fsync(struct file *file, struct dentry *dentry, int datasync)
                ret = err;
        return ret;
 }
-EXPORT_SYMBOL(simple_fsync);
+EXPORT_SYMBOL(generic_file_fsync);
+
+/*
+ * No-op implementation of ->fsync for in-memory filesystems.
+ */
+int noop_fsync(struct file *file, int datasync)
+{
+       return 0;
+}
 
 EXPORT_SYMBOL(dcache_dir_close);
 EXPORT_SYMBOL(dcache_dir_lseek);
@@ -895,7 +983,7 @@ EXPORT_SYMBOL(simple_release_fs);
 EXPORT_SYMBOL(simple_rename);
 EXPORT_SYMBOL(simple_rmdir);
 EXPORT_SYMBOL(simple_statfs);
-EXPORT_SYMBOL(simple_sync_file);
+EXPORT_SYMBOL(noop_fsync);
 EXPORT_SYMBOL(simple_unlink);
 EXPORT_SYMBOL(simple_read_from_buffer);
 EXPORT_SYMBOL(simple_write_to_buffer);
index 0de5240..abe1caf 100644 (file)
@@ -219,9 +219,9 @@ int logfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
        }
 }
 
-int logfs_fsync(struct file *file, struct dentry *dentry, int datasync)
+int logfs_fsync(struct file *file, int datasync)
 {
-       struct super_block *sb = dentry->d_inode->i_sb;
+       struct super_block *sb = file->f_mapping->host->i_sb;
 
        logfs_write_anchor(sb);
        return 0;
index 1a9db84..c838c4d 100644 (file)
@@ -506,7 +506,7 @@ extern const struct address_space_operations logfs_reg_aops;
 int logfs_readpage(struct file *file, struct page *page);
 int logfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                unsigned long arg);
-int logfs_fsync(struct file *file, struct dentry *dentry, int datasync);
+int logfs_fsync(struct file *file, int datasync);
 
 /* gc.c */
 u32 get_best_cand(struct super_block *sb, struct candidate_list *list, u32 *ec);
index 6198731..9196958 100644 (file)
@@ -22,7 +22,7 @@ const struct file_operations minix_dir_operations = {
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
        .readdir        = minix_readdir,
-       .fsync          = simple_fsync,
+       .fsync          = generic_file_fsync,
 };
 
 static inline void dir_put_page(struct page *page)
@@ -72,11 +72,8 @@ static struct page * dir_get_page(struct inode *dir, unsigned long n)
 {
        struct address_space *mapping = dir->i_mapping;
        struct page *page = read_mapping_page(mapping, n, NULL);
-       if (!IS_ERR(page)) {
+       if (!IS_ERR(page))
                kmap(page);
-               if (!PageUptodate(page))
-                       goto fail;
-       }
        return page;
 
 fail:
index 3eec3e6..d5320ff 100644 (file)
@@ -19,7 +19,7 @@ const struct file_operations minix_file_operations = {
        .write          = do_sync_write,
        .aio_write      = generic_file_aio_write,
        .mmap           = generic_file_mmap,
-       .fsync          = simple_fsync,
+       .fsync          = generic_file_fsync,
        .splice_read    = generic_file_splice_read,
 };
 
index f230109..13487ad 100644 (file)
@@ -20,6 +20,9 @@ static inline block_t *i_data(struct inode *inode)
        return (block_t *)minix_i(inode)->u.i2_data;
 }
 
+#define DIRCOUNT 7
+#define INDIRCOUNT(sb) (1 << ((sb)->s_blocksize_bits - 2))
+
 static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
 {
        int n = 0;
@@ -34,21 +37,21 @@ static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
                        printk("MINIX-fs: block_to_path: "
                               "block %ld too big on dev %s\n",
                                block, bdevname(sb->s_bdev, b));
-       } else if (block < 7) {
+       } else if (block < DIRCOUNT) {
                offsets[n++] = block;
-       } else if ((block -= 7) < 256) {
-               offsets[n++] = 7;
+       } else if ((block -= DIRCOUNT) < INDIRCOUNT(sb)) {
+               offsets[n++] = DIRCOUNT;
                offsets[n++] = block;
-       } else if ((block -= 256) < 256*256) {
-               offsets[n++] = 8;
-               offsets[n++] = block>>8;
-               offsets[n++] = block & 255;
+       } else if ((block -= INDIRCOUNT(sb)) < INDIRCOUNT(sb) * INDIRCOUNT(sb)) {
+               offsets[n++] = DIRCOUNT + 1;
+               offsets[n++] = block / INDIRCOUNT(sb);
+               offsets[n++] = block % INDIRCOUNT(sb);
        } else {
-               block -= 256*256;
-               offsets[n++] = 9;
-               offsets[n++] = block>>16;
-               offsets[n++] = (block>>8) & 255;
-               offsets[n++] = block & 255;
+               block -= INDIRCOUNT(sb) * INDIRCOUNT(sb);
+               offsets[n++] = DIRCOUNT + 2;
+               offsets[n++] = (block / INDIRCOUNT(sb)) / INDIRCOUNT(sb);
+               offsets[n++] = (block / INDIRCOUNT(sb)) % INDIRCOUNT(sb);
+               offsets[n++] = block % INDIRCOUNT(sb);
        }
        return n;
 }
index 48e1f60..868d0cb 100644 (file)
@@ -1621,6 +1621,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
        case LAST_DOTDOT:
                follow_dotdot(nd);
                dir = nd->path.dentry;
+       case LAST_DOT:
                if (nd->path.mnt->mnt_sb->s_type->fs_flags & FS_REVAL_DOT) {
                        if (!dir->d_op->d_revalidate(dir, nd)) {
                                error = -ESTALE;
@@ -1628,7 +1629,6 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
                        }
                }
                /* fallthrough */
-       case LAST_DOT:
        case LAST_ROOT:
                if (open_flag & O_CREAT)
                        goto exit;
index b938708..3639cc5 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/ncp_fs.h>
 #include "ncplib_kernel.h"
 
-static int ncp_fsync(struct file *file, struct dentry *dentry, int datasync)
+static int ncp_fsync(struct file *file, int datasync)
 {
        return 0;
 }
index db64854..782b431 100644 (file)
@@ -53,7 +53,7 @@ static int nfs_link(struct dentry *, struct inode *, struct dentry *);
 static int nfs_mknod(struct inode *, struct dentry *, int, dev_t);
 static int nfs_rename(struct inode *, struct dentry *,
                      struct inode *, struct dentry *);
-static int nfs_fsync_dir(struct file *, struct dentry *, int);
+static int nfs_fsync_dir(struct file *, int);
 static loff_t nfs_llseek_dir(struct file *, loff_t, int);
 
 const struct file_operations nfs_dir_operations = {
@@ -641,8 +641,10 @@ out:
  * All directory operations under NFS are synchronous, so fsync()
  * is a dummy operation.
  */
-static int nfs_fsync_dir(struct file *filp, struct dentry *dentry, int datasync)
+static int nfs_fsync_dir(struct file *filp, int datasync)
 {
+       struct dentry *dentry = filp->f_path.dentry;
+
        dfprintk(FILE, "NFS: fsync dir(%s/%s) datasync %d\n",
                        dentry->d_parent->d_name.name, dentry->d_name.name,
                        datasync);
index cac96bc..36a5e74 100644 (file)
@@ -53,7 +53,7 @@ static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
 static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov,
                                unsigned long nr_segs, loff_t pos);
 static int  nfs_file_flush(struct file *, fl_owner_t id);
-static int  nfs_file_fsync(struct file *, struct dentry *dentry, int datasync);
+static int  nfs_file_fsync(struct file *, int datasync);
 static int nfs_check_flags(int flags);
 static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl);
 static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl);
@@ -322,8 +322,9 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
  * whether any write errors occurred for this process.
  */
 static int
-nfs_file_fsync(struct file *file, struct dentry *dentry, int datasync)
+nfs_file_fsync(struct file *file, int datasync)
 {
+       struct dentry *dentry = file->f_path.dentry;
        struct nfs_open_context *ctx = nfs_file_open_context(file);
        struct inode *inode = dentry->d_inode;
 
index 30292df..c9a30d7 100644 (file)
@@ -27,7 +27,7 @@
 #include "nilfs.h"
 #include "segment.h"
 
-int nilfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
+int nilfs_sync_file(struct file *file, int datasync)
 {
        /*
         * Called from fsync() system call
@@ -37,7 +37,7 @@ int nilfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
         * This function should be implemented when the writeback function
         * will be implemented.
         */
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = file->f_mapping->host;
        int err;
 
        if (!nilfs_inode_dirty(inode))
index 8723e5b..47d6d79 100644 (file)
@@ -228,7 +228,7 @@ extern void nilfs_set_link(struct inode *, struct nilfs_dir_entry *,
                           struct page *, struct inode *);
 
 /* file.c */
-extern int nilfs_sync_file(struct file *, struct dentry *, int);
+extern int nilfs_sync_file(struct file *, int);
 
 /* ioctl.c */
 long nilfs_ioctl(struct file *, unsigned int, unsigned long);
index fe44d3f..0f48e7c 100644 (file)
@@ -1527,10 +1527,9 @@ static int ntfs_dir_open(struct inode *vi, struct file *filp)
  * this problem for now.  We do write the $BITMAP attribute if it is present
  * which is the important one for a directory so things are not too bad.
  */
-static int ntfs_dir_fsync(struct file *filp, struct dentry *dentry,
-               int datasync)
+static int ntfs_dir_fsync(struct file *filp, int datasync)
 {
-       struct inode *bmp_vi, *vi = dentry->d_inode;
+       struct inode *bmp_vi, *vi = filp->f_mapping->host;
        int err, ret;
        ntfs_attr na;
 
index a1924a0..113ebd9 100644 (file)
@@ -2133,7 +2133,6 @@ static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 /**
  * ntfs_file_fsync - sync a file to disk
  * @filp:      file to be synced
- * @dentry:    dentry describing the file to sync
  * @datasync:  if non-zero only flush user data and not metadata
  *
  * Data integrity sync of a file to disk.  Used for fsync, fdatasync, and msync
@@ -2149,19 +2148,15 @@ static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
  * Also, if @datasync is true, we do not wait on the inode to be written out
  * but we always wait on the page cache pages to be written out.
  *
- * Note: In the past @filp could be NULL so we ignore it as we don't need it
- * anyway.
- *
  * Locking: Caller must hold i_mutex on the inode.
  *
  * TODO: We should probably also write all attribute/index inodes associated
  * with this inode but since we have no simple way of getting to them we ignore
  * this problem for now.
  */
-static int ntfs_file_fsync(struct file *filp, struct dentry *dentry,
-               int datasync)
+static int ntfs_file_fsync(struct file *filp, int datasync)
 {
-       struct inode *vi = dentry->d_inode;
+       struct inode *vi = filp->f_mapping->host;
        int err, ret = 0;
 
        ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
index 97e54b9..6a13ea6 100644 (file)
@@ -175,13 +175,12 @@ static int ocfs2_dir_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static int ocfs2_sync_file(struct file *file,
-                          struct dentry *dentry,
-                          int datasync)
+static int ocfs2_sync_file(struct file *file, int datasync)
 {
        int err = 0;
        journal_t *journal;
-       struct inode *inode = dentry->d_inode;
+       struct dentry *dentry = file->f_path.dentry;
+       struct inode *inode = file->f_mapping->host;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
        mlog_entry("(0x%p, 0x%p, %d, '%.*s')\n", file, dentry, datasync,
@@ -1053,7 +1052,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
        }
 
        /*
-        * This will intentionally not wind up calling vmtruncate(),
+        * This will intentionally not wind up calling simple_setsize(),
         * since all the work for a size change has been done above.
         * Otherwise, we could get into problems with truncate as
         * ip_alloc_sem is used there to protect against i_size
@@ -2119,9 +2118,13 @@ relock:
                         * direct write may have instantiated a few
                         * blocks outside i_size. Trim these off again.
                         * Don't need i_size_read because we hold i_mutex.
+                        *
+                        * XXX(hch): this looks buggy because ocfs2 did not
+                        * actually implement ->truncate.  Take a look at
+                        * the new truncate sequence and update this accordingly
                         */
                        if (*ppos + count > inode->i_size)
-                               vmtruncate(inode, inode->i_size);
+                               simple_setsize(inode, inode->i_size);
                        ret = written;
                        goto out_dio;
                }
index 399487c..6e7a329 100644 (file)
@@ -329,7 +329,7 @@ const struct file_operations omfs_file_operations = {
        .aio_read = generic_file_aio_read,
        .aio_write = generic_file_aio_write,
        .mmap = generic_file_mmap,
-       .fsync = simple_fsync,
+       .fsync = generic_file_fsync,
        .splice_read = generic_file_splice_read,
 };
 
index d79872e..60da077 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -1169,14 +1169,18 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
 
        switch (cmd) {
        case F_SETPIPE_SZ:
-               if (!capable(CAP_SYS_ADMIN) && arg > pipe_max_pages)
-                       return -EINVAL;
+               if (!capable(CAP_SYS_ADMIN) && arg > pipe_max_pages) {
+                       ret = -EINVAL;
+                       goto out;
+               }
                /*
                 * The pipe needs to be at least 2 pages large to
                 * guarantee POSIX behaviour.
                 */
-               if (arg < 2)
-                       return -EINVAL;
+               if (arg < 2) {
+                       ret = -EINVAL;
+                       goto out;
+               }
                ret = pipe_set_size(pipe, arg);
                break;
        case F_GETPIPE_SZ:
@@ -1187,6 +1191,7 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
                break;
        }
 
+out:
        mutex_unlock(&pipe->inode->i_mutex);
        return ret;
 }
index 3d3fd46..6e8fc62 100644 (file)
@@ -80,7 +80,7 @@ const struct file_operations qnx4_dir_operations =
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
        .readdir        = qnx4_readdir,
-       .fsync          = simple_fsync,
+       .fsync          = generic_file_fsync,
 };
 
 const struct inode_operations qnx4_dir_inode_operations =
index 78f613c..4884ac5 100644 (file)
@@ -43,12 +43,13 @@ const struct file_operations ramfs_file_operations = {
        .write          = do_sync_write,
        .aio_write      = generic_file_aio_write,
        .mmap           = generic_file_mmap,
-       .fsync          = simple_sync_file,
+       .fsync          = noop_fsync,
        .splice_read    = generic_file_splice_read,
        .splice_write   = generic_file_splice_write,
        .llseek         = generic_file_llseek,
 };
 
 const struct inode_operations ramfs_file_inode_operations = {
+       .setattr        = simple_setattr,
        .getattr        = simple_getattr,
 };
index 5ea4ad8..d532c20 100644 (file)
@@ -42,7 +42,7 @@ const struct file_operations ramfs_file_operations = {
        .aio_read               = generic_file_aio_read,
        .write                  = do_sync_write,
        .aio_write              = generic_file_aio_write,
-       .fsync                  = simple_sync_file,
+       .fsync                  = noop_fsync,
        .splice_read            = generic_file_splice_read,
        .splice_write           = generic_file_splice_write,
        .llseek                 = generic_file_llseek,
@@ -146,7 +146,7 @@ static int ramfs_nommu_resize(struct inode *inode, loff_t newsize, loff_t size)
                        return ret;
        }
 
-       ret = vmtruncate(inode, newsize);
+       ret = simple_setsize(inode, newsize);
 
        return ret;
 }
@@ -169,7 +169,8 @@ static int ramfs_nommu_setattr(struct dentry *dentry, struct iattr *ia)
 
        /* pick out size-changing events */
        if (ia->ia_valid & ATTR_SIZE) {
-               loff_t size = i_size_read(inode);
+               loff_t size = inode->i_size;
+
                if (ia->ia_size != size) {
                        ret = ramfs_nommu_resize(inode, ia->ia_size, size);
                        if (ret < 0 || ia->ia_valid == ATTR_SIZE)
@@ -182,7 +183,7 @@ static int ramfs_nommu_setattr(struct dentry *dentry, struct iattr *ia)
                }
        }
 
-       ret = inode_setattr(inode, ia);
+       generic_setattr(inode, ia);
  out:
        ia->ia_valid = old_ia_valid;
        return ret;
index 4455fbe..198dabf 100644 (file)
@@ -14,8 +14,7 @@
 extern const struct reiserfs_key MIN_KEY;
 
 static int reiserfs_readdir(struct file *, void *, filldir_t);
-static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry,
-                             int datasync);
+static int reiserfs_dir_fsync(struct file *filp, int datasync);
 
 const struct file_operations reiserfs_dir_operations = {
        .llseek = generic_file_llseek,
@@ -28,10 +27,9 @@ const struct file_operations reiserfs_dir_operations = {
 #endif
 };
 
-static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry,
-                             int datasync)
+static int reiserfs_dir_fsync(struct file *filp, int datasync)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = filp->f_mapping->host;
        int err;
        reiserfs_write_lock(inode->i_sb);
        err = reiserfs_commit_for_inode(inode);
index 9977df9..b82cdd8 100644 (file)
@@ -134,10 +134,9 @@ static void reiserfs_vfs_truncate_file(struct inode *inode)
  * be removed...
  */
 
-static int reiserfs_sync_file(struct file *filp,
-                             struct dentry *dentry, int datasync)
+static int reiserfs_sync_file(struct file *filp, int datasync)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = filp->f_mapping->host;
        int err;
        int barrier_done;
 
index 84ecf0e..8e187a0 100644 (file)
@@ -28,8 +28,9 @@
 #include "proto.h"
 
 static int
-smb_fsync(struct file *file, struct dentry * dentry, int datasync)
+smb_fsync(struct file *file, int datasync)
 {
+       struct dentry *dentry = file->f_path.dentry;
        struct smb_sb_info *server = server_from_dentry(dentry);
        int result;
 
index dfa1d67..9551cb6 100644 (file)
@@ -714,7 +714,7 @@ smb_notify_change(struct dentry *dentry, struct iattr *attr)
                error = server->ops->truncate(inode, attr->ia_size);
                if (error)
                        goto out;
-               error = vmtruncate(inode, attr->ia_size);
+               error = simple_setsize(inode, attr->ia_size);
                if (error)
                        goto out;
                refresh = 1;
index 69688b1..a67409e 100644 (file)
@@ -946,8 +946,8 @@ out:
 EXPORT_SYMBOL_GPL(vfs_kern_mount);
 
 /**
- * freeze_super -- lock the filesystem and force it into a consistent state
- * @super: the super to lock
+ * freeze_super - lock the filesystem and force it into a consistent state
+ * @sb: the super to lock
  *
  * Syncs the super to make sure the filesystem is consistent and calls the fs's
  * freeze_fs.  Subsequent calls to this without first thawing the fs will return
index e8cbd41..c9f83f4 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -130,12 +130,10 @@ void emergency_sync(void)
 
 /*
  * Generic function to fsync a file.
- *
- * filp may be NULL if called via the msync of a vma.
  */
-int file_fsync(struct file *filp, struct dentry *dentry, int datasync)
+int file_fsync(struct file *filp, int datasync)
 {
-       struct inode * inode = dentry->d_inode;
+       struct inode *inode = filp->f_mapping->host;
        struct super_block * sb;
        int ret, err;
 
@@ -183,7 +181,7 @@ int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync)
         * livelocks in fsync_buffers_list().
         */
        mutex_lock(&mapping->host->i_mutex);
-       err = file->f_op->fsync(file, file->f_path.dentry, datasync);
+       err = file->f_op->fsync(file, datasync);
        if (!ret)
                ret = err;
        mutex_unlock(&mapping->host->i_mutex);
index bbd77e9..bde1a4c 100644 (file)
@@ -117,13 +117,11 @@ int sysfs_setattr(struct dentry *dentry, struct iattr *iattr)
        if (error)
                goto out;
 
-       iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */
-
-       error = inode_setattr(inode, iattr);
-       if (error)
-               goto out;
+       /* this ignores size changes */
+       generic_setattr(inode, iattr);
 
        error = sysfs_sd_setattr(sd, iattr);
+
 out:
        mutex_unlock(&sysfs_mutex);
        return error;
index 1dabed2..79941e4 100644 (file)
@@ -24,7 +24,7 @@ const struct file_operations sysv_dir_operations = {
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
        .readdir        = sysv_readdir,
-       .fsync          = simple_fsync,
+       .fsync          = generic_file_fsync,
 };
 
 static inline void dir_put_page(struct page *page)
index 96340c0..750cc22 100644 (file)
@@ -26,7 +26,7 @@ const struct file_operations sysv_file_operations = {
        .write          = do_sync_write,
        .aio_write      = generic_file_aio_write,
        .mmap           = generic_file_mmap,
-       .fsync          = simple_fsync,
+       .fsync          = generic_file_fsync,
        .splice_read    = generic_file_splice_read,
 };
 
index 4573734..d4a5380 100644 (file)
@@ -43,6 +43,7 @@ static int sysv_sync_fs(struct super_block *sb, int wait)
         * then attach current time stamp.
         * But if the filesystem was marked clean, keep it clean.
         */
+       sb->s_dirt = 0;
        old_time = fs32_to_cpu(sbi, *sbi->s_sb_time);
        if (sbi->s_type == FSTYPE_SYSV4) {
                if (*sbi->s_sb_state == cpu_to_fs32(sbi, 0x7c269d38 - old_time))
index 5692cf7..12f445c 100644 (file)
@@ -967,12 +967,15 @@ static int do_writepage(struct page *page, int len)
  * the page locked, and it locks @ui_mutex. However, write-back does take inode
  * @i_mutex, which means other VFS operations may be run on this inode at the
  * same time. And the problematic one is truncation to smaller size, from where
- * we have to call 'vmtruncate()', which first changes @inode->i_size, then
+ * we have to call 'simple_setsize()', which first changes @inode->i_size, then
  * drops the truncated pages. And while dropping the pages, it takes the page
- * lock. This means that 'do_truncation()' cannot call 'vmtruncate()' with
+ * lock. This means that 'do_truncation()' cannot call 'simple_setsize()' with
  * @ui_mutex locked, because it would deadlock with 'ubifs_writepage()'. This
  * means that @inode->i_size is changed while @ui_mutex is unlocked.
  *
+ * XXX: with the new truncate the above is not true anymore, the simple_setsize
+ * calls can be replaced with the individual components.
+ *
  * But in 'ubifs_writepage()' we have to guarantee that we do not write beyond
  * inode size. How do we do this if @inode->i_size may became smaller while we
  * are in the middle of 'ubifs_writepage()'? The UBIFS solution is the
@@ -1125,7 +1128,7 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode,
                budgeted = 0;
        }
 
-       err = vmtruncate(inode, new_size);
+       err = simple_setsize(inode, new_size);
        if (err)
                goto out_budg;
 
@@ -1214,7 +1217,7 @@ static int do_setattr(struct ubifs_info *c, struct inode *inode,
 
        if (attr->ia_valid & ATTR_SIZE) {
                dbg_gen("size %lld -> %lld", inode->i_size, new_size);
-               err = vmtruncate(inode, new_size);
+               err = simple_setsize(inode, new_size);
                if (err)
                        goto out;
        }
@@ -1223,7 +1226,7 @@ static int do_setattr(struct ubifs_info *c, struct inode *inode,
        if (attr->ia_valid & ATTR_SIZE) {
                /* Truncation changes inode [mc]time */
                inode->i_mtime = inode->i_ctime = ubifs_current_time(inode);
-               /* 'vmtruncate()' changed @i_size, update @ui_size */
+               /* 'simple_setsize()' changed @i_size, update @ui_size */
                ui->ui_size = inode->i_size;
        }
 
@@ -1304,9 +1307,9 @@ static void *ubifs_follow_link(struct dentry *dentry, struct nameidata *nd)
        return NULL;
 }
 
-int ubifs_fsync(struct file *file, struct dentry *dentry, int datasync)
+int ubifs_fsync(struct file *file, int datasync)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = file->f_mapping->host;
        struct ubifs_info *c = inode->i_sb->s_fs_info;
        int err;
 
index bd2542d..2eef553 100644 (file)
@@ -379,7 +379,7 @@ struct ubifs_gced_idx_leb {
  * The @ui_size is a "shadow" variable for @inode->i_size and UBIFS uses
  * @ui_size instead of @inode->i_size. The reason for this is that UBIFS cannot
  * make sure @inode->i_size is always changed under @ui_mutex, because it
- * cannot call 'vmtruncate()' with @ui_mutex locked, because it would deadlock
+ * cannot call 'simple_setsize()' with @ui_mutex locked, because it would deadlock
  * with 'ubifs_writepage()' (see file.c). All the other inode fields are
  * changed under @ui_mutex, so they do not need "shadow" fields. Note, one
  * could consider to rework locking and base it on "shadow" fields.
@@ -1678,7 +1678,7 @@ const struct ubifs_lprops *ubifs_fast_find_frdi_idx(struct ubifs_info *c);
 int ubifs_calc_dark(const struct ubifs_info *c, int spc);
 
 /* file.c */
-int ubifs_fsync(struct file *file, struct dentry *dentry, int datasync);
+int ubifs_fsync(struct file *file, int datasync);
 int ubifs_setattr(struct dentry *dentry, struct iattr *attr);
 
 /* dir.c */
index 1660c81..51552bf 100644 (file)
@@ -211,5 +211,5 @@ const struct file_operations udf_dir_operations = {
        .read                   = generic_read_dir,
        .readdir                = udf_readdir,
        .unlocked_ioctl         = udf_ioctl,
-       .fsync                  = simple_fsync,
+       .fsync                  = generic_file_fsync,
 };
index baae3a7..0660280 100644 (file)
@@ -224,7 +224,7 @@ const struct file_operations udf_file_operations = {
        .write                  = do_sync_write,
        .aio_write              = udf_file_aio_write,
        .release                = udf_release_file,
-       .fsync                  = simple_fsync,
+       .fsync                  = generic_file_fsync,
        .splice_read            = generic_file_splice_read,
        .llseek                 = generic_file_llseek,
 };
index 317a0d4..ec78475 100644 (file)
@@ -666,6 +666,6 @@ not_empty:
 const struct file_operations ufs_dir_operations = {
        .read           = generic_read_dir,
        .readdir        = ufs_readdir,
-       .fsync          = simple_fsync,
+       .fsync          = generic_file_fsync,
        .llseek         = generic_file_llseek,
 };
index a8962ce..d4c30d1 100644 (file)
@@ -42,6 +42,6 @@ const struct file_operations ufs_file_operations = {
        .aio_write      = generic_file_aio_write,
        .mmap           = generic_file_mmap,
        .open           = dquot_file_open,
-       .fsync          = simple_fsync,
+       .fsync          = generic_file_fsync,
        .splice_read    = generic_file_splice_read,
 };
index f294c44..3733057 100644 (file)
@@ -501,12 +501,10 @@ out:
        return err;
 }
 
-
 /*
- * We don't define our `inode->i_op->truncate', and call it here,
- * because of:
- * - there is no way to know old size
- * - there is no way inform user about error, if it happens in `truncate'
+ * TODO:
+ *     - truncate case should use proper ordering instead of using
+ *       simple_setsize
  */
 int ufs_setattr(struct dentry *dentry, struct iattr *attr)
 {
@@ -530,7 +528,7 @@ int ufs_setattr(struct dentry *dentry, struct iattr *attr)
        if (ia_valid & ATTR_SIZE && attr->ia_size != inode->i_size) {
                loff_t old_i_size = inode->i_size;
 
-               error = vmtruncate(inode, attr->ia_size);
+               error = simple_setsize(inode, attr->ia_size);
                if (error)
                        return error;
                error = ufs_truncate(inode, old_i_size);
index d8fb1b5..257a56b 100644 (file)
@@ -100,10 +100,10 @@ xfs_iozero(
 STATIC int
 xfs_file_fsync(
        struct file             *file,
-       struct dentry           *dentry,
        int                     datasync)
 {
-       struct xfs_inode        *ip = XFS_I(dentry->d_inode);
+       struct inode            *inode = file->f_mapping->host;
+       struct xfs_inode        *ip = XFS_I(inode);
        struct xfs_trans        *tp;
        int                     error = 0;
        int                     log_flushed = 0;
@@ -140,8 +140,8 @@ xfs_file_fsync(
         * might gets cleared when the inode gets written out via the AIL
         * or xfs_iflush_cluster.
         */
-       if (((dentry->d_inode->i_state & I_DIRTY_DATASYNC) ||
-           ((dentry->d_inode->i_state & I_DIRTY_SYNC) && !datasync)) &&
+       if (((inode->i_state & I_DIRTY_DATASYNC) ||
+           ((inode->i_state & I_DIRTY_SYNC) && !datasync)) &&
            ip->i_update_core) {
                /*
                 * Kick off a transaction to log the inode core to get the
@@ -868,7 +868,7 @@ write_retry:
                        mutex_lock(&inode->i_mutex);
                xfs_ilock(ip, iolock);
 
-               error2 = -xfs_file_fsync(file, file->f_path.dentry,
+               error2 = -xfs_file_fsync(file,
                                         (file->f_flags & __O_SYNC) ? 0 : 1);
                if (!error)
                        error = error2;
index 16ed028..1b9ba19 100644 (file)
@@ -203,6 +203,9 @@ int block_write_full_page_endio(struct page *page, get_block_t *get_block,
 int block_read_full_page(struct page*, get_block_t*);
 int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc,
                                unsigned long from);
+int block_write_begin_newtrunc(struct file *, struct address_space *,
+                               loff_t, unsigned, unsigned,
+                               struct page **, void **, get_block_t*);
 int block_write_begin(struct file *, struct address_space *,
                                loff_t, unsigned, unsigned,
                                struct page **, void **, get_block_t*);
@@ -214,6 +217,9 @@ int generic_write_end(struct file *, struct address_space *,
                                struct page *, void *);
 void page_zero_new_buffers(struct page *page, unsigned from, unsigned to);
 int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*);
+int cont_write_begin_newtrunc(struct file *, struct address_space *, loff_t,
+                       unsigned, unsigned, struct page **, void **,
+                       get_block_t *, loff_t *);
 int cont_write_begin(struct file *, struct address_space *, loff_t,
                        unsigned, unsigned, struct page **, void **,
                        get_block_t *, loff_t *);
@@ -224,7 +230,10 @@ int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
 void block_sync_page(struct page *);
 sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *);
 int block_truncate_page(struct address_space *, loff_t, get_block_t *);
-int file_fsync(struct file *, struct dentry *, int);
+int file_fsync(struct file *, int);
+int nobh_write_begin_newtrunc(struct file *, struct address_space *,
+                               loff_t, unsigned, unsigned,
+                               struct page **, void **, get_block_t*);
 int nobh_write_begin(struct file *, struct address_space *,
                                loff_t, unsigned, unsigned,
                                struct page **, void **, get_block_t*);
index 5f494b4..7fc62d4 100644 (file)
@@ -868,7 +868,7 @@ extern int ext3_htree_store_dirent(struct file *dir_file, __u32 hash,
 extern void ext3_htree_free_dir_info(struct dir_private_info *p);
 
 /* fsync.c */
-extern int ext3_sync_file (struct file *, struct dentry *, int);
+extern int ext3_sync_file(struct file *, int);
 
 /* hash.c */
 extern int ext3fs_dirhash(const char *name, int len, struct
index f3793eb..907ace3 100644 (file)
@@ -4,8 +4,6 @@
 #include <linux/types.h>
 #include <linux/i2c.h>
 
-struct dentry;
-
 /* Definitions of frame buffers                                                */
 
 #define FB_MAX                 32      /* sufficient for now */
@@ -1017,8 +1015,7 @@ extern void fb_deferred_io_open(struct fb_info *info,
                                struct inode *inode,
                                struct file *file);
 extern void fb_deferred_io_cleanup(struct fb_info *info);
-extern int fb_deferred_io_fsync(struct file *file, struct dentry *dentry,
-                               int datasync);
+extern int fb_deferred_io_fsync(struct file *file, int datasync);
 
 static inline bool fb_be_math(struct fb_info *info)
 {
index 5555508..b1e1297 100644 (file)
@@ -11,7 +11,6 @@
 
 struct file;
 
-extern void __fput(struct file *);
 extern void fput(struct file *);
 extern void drop_file_write_access(struct file *file);
 
index 85e823a..3428393 100644 (file)
@@ -954,6 +954,7 @@ extern spinlock_t files_lock;
 #define file_list_unlock() spin_unlock(&files_lock);
 
 #define get_file(x)    atomic_long_inc(&(x)->f_count)
+#define fput_atomic(x) atomic_long_add_unless(&(x)->f_count, -1, 1)
 #define file_count(x)  atomic_long_read(&(x)->f_count)
 
 #ifdef CONFIG_DEBUG_WRITECOUNT
@@ -1497,7 +1498,7 @@ struct file_operations {
        int (*open) (struct inode *, struct file *);
        int (*flush) (struct file *, fl_owner_t id);
        int (*release) (struct inode *, struct file *);
-       int (*fsync) (struct file *, struct dentry *, int datasync);
+       int (*fsync) (struct file *, int datasync);
        int (*aio_fsync) (struct kiocb *, int datasync);
        int (*fasync) (int, struct file *, int);
        int (*lock) (struct file *, int, struct file_lock *);
@@ -2212,7 +2213,7 @@ extern int generic_segment_checks(const struct iovec *iov,
 /* fs/block_dev.c */
 extern ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,
                                unsigned long nr_segs, loff_t pos);
-extern int blkdev_fsync(struct file *filp, struct dentry *dentry, int datasync);
+extern int blkdev_fsync(struct file *filp, int datasync);
 
 /* fs/splice.c */
 extern ssize_t generic_file_splice_read(struct file *, loff_t *,
@@ -2256,6 +2257,10 @@ typedef void (dio_submit_t)(int rw, struct bio *bio, struct inode *inode,
                            loff_t file_offset);
 void dio_end_io(struct bio *bio, int error);
 
+ssize_t __blockdev_direct_IO_newtrunc(int rw, struct kiocb *iocb, struct inode *inode,
+       struct block_device *bdev, const struct iovec *iov, loff_t offset,
+       unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io,
+       dio_submit_t submit_io, int lock_type);
 ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
        struct block_device *bdev, const struct iovec *iov, loff_t offset,
        unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io,
@@ -2269,6 +2274,24 @@ enum {
        DIO_SKIP_HOLES  = 0x02,
 };
 
+static inline ssize_t blockdev_direct_IO_newtrunc(int rw, struct kiocb *iocb,
+       struct inode *inode, struct block_device *bdev, const struct iovec *iov,
+       loff_t offset, unsigned long nr_segs, get_block_t get_block,
+       dio_iodone_t end_io)
+{
+       return __blockdev_direct_IO_newtrunc(rw, iocb, inode, bdev, iov, offset,
+                                   nr_segs, get_block, end_io, NULL,
+                                   DIO_LOCKING | DIO_SKIP_HOLES);
+}
+
+static inline ssize_t blockdev_direct_IO_no_locking_newtrunc(int rw, struct kiocb *iocb,
+       struct inode *inode, struct block_device *bdev, const struct iovec *iov,
+       loff_t offset, unsigned long nr_segs, get_block_t get_block,
+       dio_iodone_t end_io)
+{
+       return __blockdev_direct_IO_newtrunc(rw, iocb, inode, bdev, iov, offset,
+                               nr_segs, get_block, end_io, NULL, 0);
+}
 static inline ssize_t blockdev_direct_IO(int rw, struct kiocb *iocb,
        struct inode *inode, struct block_device *bdev, const struct iovec *iov,
        loff_t offset, unsigned long nr_segs, get_block_t get_block,
@@ -2341,13 +2364,15 @@ extern int dcache_dir_open(struct inode *, struct file *);
 extern int dcache_dir_close(struct inode *, struct file *);
 extern loff_t dcache_dir_lseek(struct file *, loff_t, int);
 extern int dcache_readdir(struct file *, void *, filldir_t);
+extern int simple_setattr(struct dentry *, struct iattr *);
 extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 extern int simple_statfs(struct dentry *, struct kstatfs *);
 extern int simple_link(struct dentry *, struct inode *, struct dentry *);
 extern int simple_unlink(struct inode *, struct dentry *);
 extern int simple_rmdir(struct inode *, struct dentry *);
 extern int simple_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
-extern int simple_sync_file(struct file *, struct dentry *, int);
+extern int simple_setsize(struct inode *, loff_t);
+extern int noop_fsync(struct file *, int);
 extern int simple_empty(struct dentry *);
 extern int simple_readpage(struct file *file, struct page *page);
 extern int simple_write_begin(struct file *file, struct address_space *mapping,
@@ -2372,7 +2397,7 @@ extern ssize_t simple_read_from_buffer(void __user *to, size_t count,
 extern ssize_t simple_write_to_buffer(void *to, size_t available, loff_t *ppos,
                const void __user *from, size_t count);
 
-extern int simple_fsync(struct file *, struct dentry *, int);
+extern int generic_file_fsync(struct file *, int);
 
 #ifdef CONFIG_MIGRATION
 extern int buffer_migrate_page(struct address_space *,
@@ -2383,7 +2408,8 @@ extern int buffer_migrate_page(struct address_space *,
 
 extern int inode_change_ok(const struct inode *, struct iattr *);
 extern int inode_newsize_ok(const struct inode *, loff_t offset);
-extern int __must_check inode_setattr(struct inode *, struct iattr *);
+extern int __must_check inode_setattr(struct inode *, const struct iattr *);
+extern void generic_setattr(struct inode *inode, const struct iattr *attr);
 
 extern void file_update_time(struct file *file);
 
index ee84e7e..3bad270 100644 (file)
@@ -386,6 +386,7 @@ enum {
        ATA_HORKAGE_1_5_GBPS    = (1 << 13),    /* force 1.5 Gbps */
        ATA_HORKAGE_NOSETXFER   = (1 << 14),    /* skip SETXFER, SATA only */
        ATA_HORKAGE_BROKEN_FPDMA_AA     = (1 << 15),    /* skip AA */
+       ATA_HORKAGE_DUMP_ID     = (1 << 16),    /* dump IDENTIFY data */
 
         /* DMA mask for user DMA control: User visible values; DO NOT
            renumber */
@@ -513,7 +514,9 @@ struct ata_ioports {
        void __iomem            *command_addr;
        void __iomem            *altstatus_addr;
        void __iomem            *ctl_addr;
+#ifdef CONFIG_ATA_BMDMA
        void __iomem            *bmdma_addr;
+#endif /* CONFIG_ATA_BMDMA */
        void __iomem            *scr_addr;
 };
 #endif /* CONFIG_ATA_SFF */
@@ -721,8 +724,10 @@ struct ata_port {
        u8                      ctl;    /* cache of ATA control register */
        u8                      last_ctl;       /* Cache last written value */
        struct delayed_work     sff_pio_task;
+#ifdef CONFIG_ATA_BMDMA
        struct ata_bmdma_prd    *bmdma_prd;     /* BMDMA SG list */
        dma_addr_t              bmdma_prd_dma;  /* and its DMA mapping */
+#endif /* CONFIG_ATA_BMDMA */
 #endif /* CONFIG_ATA_SFF */
 
        unsigned int            pio_mask;
@@ -856,10 +861,12 @@ struct ata_port_operations {
        void (*sff_irq_clear)(struct ata_port *);
        void (*sff_drain_fifo)(struct ata_queued_cmd *qc);
 
+#ifdef CONFIG_ATA_BMDMA
        void (*bmdma_setup)(struct ata_queued_cmd *qc);
        void (*bmdma_start)(struct ata_queued_cmd *qc);
        void (*bmdma_stop)(struct ata_queued_cmd *qc);
        u8   (*bmdma_status)(struct ata_port *ap);
+#endif /* CONFIG_ATA_BMDMA */
 #endif /* CONFIG_ATA_SFF */
 
        ssize_t (*em_show)(struct ata_port *ap, char *buf);
@@ -1555,7 +1562,6 @@ extern void sata_pmp_error_handler(struct ata_port *ap);
 #ifdef CONFIG_ATA_SFF
 
 extern const struct ata_port_operations ata_sff_port_ops;
-extern const struct ata_port_operations ata_bmdma_port_ops;
 extern const struct ata_port_operations ata_bmdma32_port_ops;
 
 /* PIO only, sg_tablesize and dma_boundary limits can be removed */
@@ -1564,11 +1570,6 @@ extern const struct ata_port_operations ata_bmdma32_port_ops;
        .sg_tablesize           = LIBATA_MAX_PRD,               \
        .dma_boundary           = ATA_DMA_BOUNDARY
 
-#define ATA_BMDMA_SHT(drv_name)                                        \
-       ATA_BASE_SHT(drv_name),                                 \
-       .sg_tablesize           = LIBATA_MAX_PRD,               \
-       .dma_boundary           = ATA_DMA_BOUNDARY
-
 extern void ata_sff_dev_select(struct ata_port *ap, unsigned int device);
 extern u8 ata_sff_check_status(struct ata_port *ap);
 extern void ata_sff_pause(struct ata_port *ap);
@@ -1593,7 +1594,7 @@ extern int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
 extern void ata_sff_queue_pio_task(struct ata_port *ap, unsigned long delay);
 extern unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc);
 extern bool ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc);
-extern unsigned int ata_sff_host_intr(struct ata_port *ap,
+extern unsigned int ata_sff_port_intr(struct ata_port *ap,
                                      struct ata_queued_cmd *qc);
 extern irqreturn_t ata_sff_interrupt(int irq, void *dev_instance);
 extern void ata_sff_lost_interrupt(struct ata_port *ap);
@@ -1625,11 +1626,24 @@ extern int ata_pci_sff_init_one(struct pci_dev *pdev,
                struct scsi_host_template *sht, void *host_priv, int hflags);
 #endif /* CONFIG_PCI */
 
+#ifdef CONFIG_ATA_BMDMA
+
+extern const struct ata_port_operations ata_bmdma_port_ops;
+
+#define ATA_BMDMA_SHT(drv_name)                                        \
+       ATA_BASE_SHT(drv_name),                                 \
+       .sg_tablesize           = LIBATA_MAX_PRD,               \
+       .dma_boundary           = ATA_DMA_BOUNDARY
+
 extern void ata_bmdma_qc_prep(struct ata_queued_cmd *qc);
 extern unsigned int ata_bmdma_qc_issue(struct ata_queued_cmd *qc);
 extern void ata_bmdma_dumb_qc_prep(struct ata_queued_cmd *qc);
+extern unsigned int ata_bmdma_port_intr(struct ata_port *ap,
+                                     struct ata_queued_cmd *qc);
+extern irqreturn_t ata_bmdma_interrupt(int irq, void *dev_instance);
 extern void ata_bmdma_error_handler(struct ata_port *ap);
 extern void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc);
+extern void ata_bmdma_irq_clear(struct ata_port *ap);
 extern void ata_bmdma_setup(struct ata_queued_cmd *qc);
 extern void ata_bmdma_start(struct ata_queued_cmd *qc);
 extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
@@ -1640,7 +1654,15 @@ extern int ata_bmdma_port_start32(struct ata_port *ap);
 #ifdef CONFIG_PCI
 extern int ata_pci_bmdma_clear_simplex(struct pci_dev *pdev);
 extern void ata_pci_bmdma_init(struct ata_host *host);
+extern int ata_pci_bmdma_prepare_host(struct pci_dev *pdev,
+                                     const struct ata_port_info * const * ppi,
+                                     struct ata_host **r_host);
+extern int ata_pci_bmdma_init_one(struct pci_dev *pdev,
+                                 const struct ata_port_info * const * ppi,
+                                 struct scsi_host_template *sht,
+                                 void *host_priv, int hflags);
 #endif /* CONFIG_PCI */
+#endif /* CONFIG_ATA_BMDMA */
 
 /**
  *     ata_sff_busy_wait - Wait for a port status register
index 6cf4486..726cc35 100644 (file)
@@ -39,7 +39,7 @@ extern int net_cls_subsys_id;
 static inline u32 task_cls_classid(struct task_struct *p)
 {
        int id;
-       u32 classid;
+       u32 classid = 0;
 
        if (in_interrupt())
                return 0;
index 6173c61..4b86011 100644 (file)
@@ -876,7 +876,7 @@ struct sctp_transport {
 
        /* Reference counting. */
        atomic_t refcnt;
-       int      dead:1,
+       __u32    dead:1,
                /* RTO-Pending : A flag used to track if one of the DATA
                 *              chunks sent to this address is currently being
                 *              used to compute a RTT. If this flag is 0,
index d2a71b0..ca241ea 100644 (file)
@@ -1026,15 +1026,23 @@ extern void release_sock(struct sock *sk);
                                SINGLE_DEPTH_NESTING)
 #define bh_unlock_sock(__sk)   spin_unlock(&((__sk)->sk_lock.slock))
 
-static inline void lock_sock_bh(struct sock *sk)
+extern bool lock_sock_fast(struct sock *sk);
+/**
+ * unlock_sock_fast - complement of lock_sock_fast
+ * @sk: socket
+ * @slow: slow mode
+ *
+ * fast unlock socket for user context.
+ * If slow mode is on, we call regular release_sock()
+ */
+static inline void unlock_sock_fast(struct sock *sk, bool slow)
 {
-       spin_lock_bh(&sk->sk_lock.slock);
+       if (slow)
+               release_sock(sk);
+       else
+               spin_unlock_bh(&sk->sk_lock.slock);
 }
 
-static inline void unlock_sock_bh(struct sock *sk)
-{
-       spin_unlock_bh(&sk->sk_lock.slock);
-}
 
 extern struct sock             *sk_alloc(struct net *net, int family,
                                          gfp_t priority,
index 5d60ad4..f5b1ba9 100644 (file)
@@ -606,9 +606,9 @@ TRACE_EVENT(ext4_free_blocks,
 );
 
 TRACE_EVENT(ext4_sync_file,
-       TP_PROTO(struct file *file, struct dentry *dentry, int datasync),
+       TP_PROTO(struct file *file, int datasync),
 
-       TP_ARGS(file, dentry, datasync),
+       TP_ARGS(file, datasync),
 
        TP_STRUCT__entry(
                __field(        dev_t,  dev                     )
@@ -618,6 +618,8 @@ TRACE_EVENT(ext4_sync_file,
        ),
 
        TP_fast_assign(
+               struct dentry *dentry = file->f_path.dentry;
+
                __entry->dev            = dentry->d_inode->i_sb->s_dev;
                __entry->ino            = dentry->d_inode->i_ino;
                __entry->datasync       = datasync;
index 1a314c8..52ed77e 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -273,16 +273,13 @@ static int shm_release(struct inode *ino, struct file *file)
        return 0;
 }
 
-static int shm_fsync(struct file *file, struct dentry *dentry, int datasync)
+static int shm_fsync(struct file *file, int datasync)
 {
-       int (*fsync) (struct file *, struct dentry *, int datasync);
        struct shm_file_data *sfd = shm_file_data(file);
-       int ret = -EINVAL;
 
-       fsync = sfd->file->f_op->fsync;
-       if (fsync)
-               ret = fsync(sfd->file, sfd->file->f_path.dentry, datasync);
-       return ret;
+       if (!sfd->file->f_op->fsync)
+               return -EINVAL;
+       return sfd->file->f_op->fsync(sfd->file, datasync);
 }
 
 static unsigned long shm_get_unmapped_area(struct file *file,
index b9b134b..5c69e99 100644 (file)
@@ -89,7 +89,7 @@ static void hrtimer_get_softirq_time(struct hrtimer_cpu_base *base)
 
        do {
                seq = read_seqbegin(&xtime_lock);
-               xts = current_kernel_time();
+               xts = __current_kernel_time();
                tom = wall_to_monotonic;
        } while (read_seqretry(&xtime_lock, seq));
 
index e099650..bd7ce8c 100644 (file)
@@ -4999,8 +4999,8 @@ SYSCALL_DEFINE5(perf_event_open,
        struct perf_event_context *ctx;
        struct file *event_file = NULL;
        struct file *group_file = NULL;
+       int event_fd;
        int fput_needed = 0;
-       int fput_needed2 = 0;
        int err;
 
        /* for future expandability... */
@@ -5021,12 +5021,18 @@ SYSCALL_DEFINE5(perf_event_open,
                        return -EINVAL;
        }
 
+       event_fd = get_unused_fd_flags(O_RDWR);
+       if (event_fd < 0)
+               return event_fd;
+
        /*
         * Get the target context (task or percpu):
         */
        ctx = find_get_context(pid, cpu);
-       if (IS_ERR(ctx))
-               return PTR_ERR(ctx);
+       if (IS_ERR(ctx)) {
+               err = PTR_ERR(ctx);
+               goto err_fd;
+       }
 
        /*
         * Look up the group leader (we will attach this event to it):
@@ -5066,13 +5072,11 @@ SYSCALL_DEFINE5(perf_event_open,
        if (IS_ERR(event))
                goto err_put_context;
 
-       err = anon_inode_getfd("[perf_event]", &perf_fops, event, O_RDWR);
-       if (err < 0)
-               goto err_free_put_context;
-
-       event_file = fget_light(err, &fput_needed2);
-       if (!event_file)
+       event_file = anon_inode_getfile("[perf_event]", &perf_fops, event, O_RDWR);
+       if (IS_ERR(event_file)) {
+               err = PTR_ERR(event_file);
                goto err_free_put_context;
+       }
 
        if (flags & PERF_FLAG_FD_OUTPUT) {
                err = perf_event_set_output(event, group_fd);
@@ -5093,19 +5097,19 @@ SYSCALL_DEFINE5(perf_event_open,
        list_add_tail(&event->owner_entry, &current->perf_event_list);
        mutex_unlock(&current->perf_event_mutex);
 
-err_fput_free_put_context:
-       fput_light(event_file, fput_needed2);
+       fput_light(group_file, fput_needed);
+       fd_install(event_fd, event_file);
+       return event_fd;
 
+err_fput_free_put_context:
+       fput(event_file);
 err_free_put_context:
-       if (err < 0)
-               free_event(event);
-
+       free_event(event);
 err_put_context:
-       if (err < 0)
-               put_ctx(ctx);
-
        fput_light(group_file, fput_needed);
-
+       put_ctx(ctx);
+err_fd:
+       put_unused_fd(event_fd);
        return err;
 }
 
index 00d1fda..ad72342 100644 (file)
@@ -559,14 +559,7 @@ SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock,
        new_timer->it_id = (timer_t) new_timer_id;
        new_timer->it_clock = which_clock;
        new_timer->it_overrun = -1;
-       error = CLOCK_DISPATCH(which_clock, timer_create, (new_timer));
-       if (error)
-               goto out;
 
-       /*
-        * return the timer_id now.  The next step is hard to
-        * back out if there is an error.
-        */
        if (copy_to_user(created_timer_id,
                         &new_timer_id, sizeof (new_timer_id))) {
                error = -EFAULT;
@@ -597,6 +590,10 @@ SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock,
        new_timer->sigq->info.si_tid   = new_timer->it_id;
        new_timer->sigq->info.si_code  = SI_TIMER;
 
+       error = CLOCK_DISPATCH(which_clock, timer_create, (new_timer));
+       if (error)
+               goto out;
+
        spin_lock_irq(&current->sighand->siglock);
        new_timer->it_signal = current->signal;
        list_add(&new_timer->list, &current->signal->posix_timers);
index e3b8c69..2454172 100644 (file)
@@ -752,11 +752,15 @@ unsigned long apply_slack(struct timer_list *timer, unsigned long expires)
 
        expires_limit = expires;
 
-       if (timer->slack > -1)
+       if (timer->slack >= 0) {
                expires_limit = expires + timer->slack;
-       else if (time_after(expires, jiffies)) /* auto slack: use 0.4% */
-               expires_limit = expires + (expires - jiffies)/256;
+       } else {
+               unsigned long now = jiffies;
 
+               /* No slack, if already expired else auto slack 0.4% */
+               if (time_after(expires, now))
+                       expires_limit = expires + (expires - now)/256;
+       }
        mask = expires ^ expires_limit;
        if (mask == 0)
                return expires;
index 855eaf5..7e5030a 100644 (file)
@@ -727,10 +727,11 @@ done2:
        if (inode->i_mapping->nrpages && (info->flags & SHMEM_PAGEIN)) {
                /*
                 * Call truncate_inode_pages again: racing shmem_unuse_inode
-                * may have swizzled a page in from swap since vmtruncate or
-                * generic_delete_inode did it, before we lowered next_index.
-                * Also, though shmem_getpage checks i_size before adding to
-                * cache, no recheck after: so fix the narrow window there too.
+                * may have swizzled a page in from swap since
+                * truncate_pagecache or generic_delete_inode did it, before we
+                * lowered next_index.  Also, though shmem_getpage checks
+                * i_size before adding to cache, no recheck after: so fix the
+                * narrow window there too.
                 *
                 * Recalling truncate_inode_pages_range and unmap_mapping_range
                 * every time for punch_hole (which never got a chance to clear
@@ -760,19 +761,16 @@ done2:
        }
 }
 
-static void shmem_truncate(struct inode *inode)
-{
-       shmem_truncate_range(inode, inode->i_size, (loff_t)-1);
-}
-
 static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
 {
        struct inode *inode = dentry->d_inode;
-       struct page *page = NULL;
        int error;
 
        if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
-               if (attr->ia_size < inode->i_size) {
+               loff_t newsize = attr->ia_size;
+               struct page *page = NULL;
+
+               if (newsize < inode->i_size) {
                        /*
                         * If truncating down to a partial page, then
                         * if that page is already allocated, hold it
@@ -780,9 +778,9 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
                         * truncate_partial_page cannnot miss it were
                         * it assigned to swap.
                         */
-                       if (attr->ia_size & (PAGE_CACHE_SIZE-1)) {
+                       if (newsize & (PAGE_CACHE_SIZE-1)) {
                                (void) shmem_getpage(inode,
-                                       attr->ia_size>>PAGE_CACHE_SHIFT,
+                                       newsize >> PAGE_CACHE_SHIFT,
                                                &page, SGP_READ, NULL);
                                if (page)
                                        unlock_page(page);
@@ -794,24 +792,29 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
                         * if it's being fully truncated to zero-length: the
                         * nrpages check is efficient enough in that case.
                         */
-                       if (attr->ia_size) {
+                       if (newsize) {
                                struct shmem_inode_info *info = SHMEM_I(inode);
                                spin_lock(&info->lock);
                                info->flags &= ~SHMEM_PAGEIN;
                                spin_unlock(&info->lock);
                        }
                }
+
+               error = simple_setsize(inode, newsize);
+               if (page)
+                       page_cache_release(page);
+               if (error)
+                       return error;
+               shmem_truncate_range(inode, newsize, (loff_t)-1);
        }
 
        error = inode_change_ok(inode, attr);
        if (!error)
-               error = inode_setattr(inode, attr);
+               generic_setattr(inode, attr);
 #ifdef CONFIG_TMPFS_POSIX_ACL
        if (!error && (attr->ia_valid & ATTR_MODE))
                error = generic_acl_chmod(inode);
 #endif
-       if (page)
-               page_cache_release(page);
        return error;
 }
 
@@ -819,11 +822,11 @@ static void shmem_delete_inode(struct inode *inode)
 {
        struct shmem_inode_info *info = SHMEM_I(inode);
 
-       if (inode->i_op->truncate == shmem_truncate) {
+       if (inode->i_mapping->a_ops == &shmem_aops) {
                truncate_inode_pages(inode->i_mapping, 0);
                shmem_unacct_size(info->flags, inode->i_size);
                inode->i_size = 0;
-               shmem_truncate(inode);
+               shmem_truncate_range(inode, 0, (loff_t)-1);
                if (!list_empty(&info->swaplist)) {
                        mutex_lock(&shmem_swaplist_mutex);
                        list_del_init(&info->swaplist);
@@ -2022,7 +2025,6 @@ static const struct inode_operations shmem_symlink_inline_operations = {
 };
 
 static const struct inode_operations shmem_symlink_inode_operations = {
-       .truncate       = shmem_truncate,
        .readlink       = generic_readlink,
        .follow_link    = shmem_follow_link,
        .put_link       = shmem_put_link,
@@ -2433,14 +2435,13 @@ static const struct file_operations shmem_file_operations = {
        .write          = do_sync_write,
        .aio_read       = shmem_file_aio_read,
        .aio_write      = generic_file_aio_write,
-       .fsync          = simple_sync_file,
+       .fsync          = noop_fsync,
        .splice_read    = generic_file_splice_read,
        .splice_write   = generic_file_splice_write,
 #endif
 };
 
 static const struct inode_operations shmem_inode_operations = {
-       .truncate       = shmem_truncate,
        .setattr        = shmem_notify_change,
        .truncate_range = shmem_truncate_range,
 #ifdef CONFIG_TMPFS_POSIX_ACL
index f42675a..937571b 100644 (file)
@@ -548,18 +548,18 @@ EXPORT_SYMBOL(truncate_pagecache);
  * NOTE! We have to be ready to update the memory sharing
  * between the file and the memory map for a potential last
  * incomplete page.  Ugly, but necessary.
+ *
+ * This function is deprecated and simple_setsize or truncate_pagecache
+ * should be used instead.
  */
 int vmtruncate(struct inode *inode, loff_t offset)
 {
-       loff_t oldsize;
        int error;
 
-       error = inode_newsize_ok(inode, offset);
+       error = simple_setsize(inode, offset);
        if (error)
                return error;
-       oldsize = inode->i_size;
-       i_size_write(inode, offset);
-       truncate_pagecache(inode, oldsize, offset);
+
        if (inode->i_op->truncate)
                inode->i_op->truncate(inode);
 
index e009753..f5b6f43 100644 (file)
@@ -229,15 +229,17 @@ EXPORT_SYMBOL(skb_free_datagram);
 
 void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb)
 {
+       bool slow;
+
        if (likely(atomic_read(&skb->users) == 1))
                smp_rmb();
        else if (likely(!atomic_dec_and_test(&skb->users)))
                return;
 
-       lock_sock_bh(sk);
+       slow = lock_sock_fast(sk);
        skb_orphan(skb);
        sk_mem_reclaim_partial(sk);
-       unlock_sock_bh(sk);
+       unlock_sock_fast(sk, slow);
 
        /* skb is now orphaned, can be freed outside of locked section */
        __kfree_skb(skb);
index bff3790..6ba1c0e 100644 (file)
@@ -934,6 +934,7 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
                                kfree_skb(buff);
                                NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);
                        }
+                       skb_dst_force(skb);
                        __skb_queue_tail(&neigh->arp_queue, skb);
                }
                rc = 1;
index 7ab86f3..1a2af24 100644 (file)
@@ -650,11 +650,12 @@ static inline int rtnl_vfinfo_size(const struct net_device *dev)
        if (dev->dev.parent && dev_is_pci(dev->dev.parent)) {
 
                int num_vfs = dev_num_vf(dev->dev.parent);
-               size_t size = nlmsg_total_size(sizeof(struct nlattr));
-               size += nlmsg_total_size(num_vfs * sizeof(struct nlattr));
-               size += num_vfs * (sizeof(struct ifla_vf_mac) +
-                                 sizeof(struct ifla_vf_vlan) +
-                                 sizeof(struct ifla_vf_tx_rate));
+               size_t size = nla_total_size(sizeof(struct nlattr));
+               size += nla_total_size(num_vfs * sizeof(struct nlattr));
+               size += num_vfs *
+                       (nla_total_size(sizeof(struct ifla_vf_mac)) +
+                        nla_total_size(sizeof(struct ifla_vf_vlan)) +
+                        nla_total_size(sizeof(struct ifla_vf_tx_rate)));
                return size;
        } else
                return 0;
@@ -722,14 +723,13 @@ static int rtnl_vf_ports_fill(struct sk_buff *skb, struct net_device *dev)
 
        for (vf = 0; vf < dev_num_vf(dev->dev.parent); vf++) {
                vf_port = nla_nest_start(skb, IFLA_VF_PORT);
-               if (!vf_port) {
-                       nla_nest_cancel(skb, vf_ports);
-                       return -EMSGSIZE;
-               }
+               if (!vf_port)
+                       goto nla_put_failure;
                NLA_PUT_U32(skb, IFLA_PORT_VF, vf);
                err = dev->netdev_ops->ndo_get_vf_port(dev, vf, skb);
+               if (err == -EMSGSIZE)
+                       goto nla_put_failure;
                if (err) {
-nla_put_failure:
                        nla_nest_cancel(skb, vf_port);
                        continue;
                }
@@ -739,6 +739,10 @@ nla_put_failure:
        nla_nest_end(skb, vf_ports);
 
        return 0;
+
+nla_put_failure:
+       nla_nest_cancel(skb, vf_ports);
+       return -EMSGSIZE;
 }
 
 static int rtnl_port_self_fill(struct sk_buff *skb, struct net_device *dev)
@@ -753,7 +757,7 @@ static int rtnl_port_self_fill(struct sk_buff *skb, struct net_device *dev)
        err = dev->netdev_ops->ndo_get_vf_port(dev, PORT_SELF_VF, skb);
        if (err) {
                nla_nest_cancel(skb, port_self);
-               return err;
+               return (err == -EMSGSIZE) ? err : 0;
        }
 
        nla_nest_end(skb, port_self);
index 37fe9b6..2cf7f9f 100644 (file)
@@ -2007,6 +2007,39 @@ void release_sock(struct sock *sk)
 }
 EXPORT_SYMBOL(release_sock);
 
+/**
+ * lock_sock_fast - fast version of lock_sock
+ * @sk: socket
+ *
+ * This version should be used for very small section, where process wont block
+ * return false if fast path is taken
+ *   sk_lock.slock locked, owned = 0, BH disabled
+ * return true if slow path is taken
+ *   sk_lock.slock unlocked, owned = 1, BH enabled
+ */
+bool lock_sock_fast(struct sock *sk)
+{
+       might_sleep();
+       spin_lock_bh(&sk->sk_lock.slock);
+
+       if (!sk->sk_lock.owned)
+               /*
+                * Note : We must disable BH
+                */
+               return false;
+
+       __lock_sock(sk);
+       sk->sk_lock.owned = 1;
+       spin_unlock(&sk->sk_lock.slock);
+       /*
+        * The sk_lock has mutex_lock() semantics here:
+        */
+       mutex_acquire(&sk->sk_lock.dep_map, 0, 0, _RET_IP_);
+       local_bh_enable();
+       return true;
+}
+EXPORT_SYMBOL(lock_sock_fast);
+
 int sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp)
 {
        struct timeval tv;
index 4588910..856123f 100644 (file)
@@ -1911,7 +1911,7 @@ static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
        struct rtattr *mp_head;
 
        /* If cache is unresolved, don't try to parse IIF and OIF */
-       if (c->mfc_parent > MAXVIFS)
+       if (c->mfc_parent >= MAXVIFS)
                return -ENOENT;
 
        if (VIF_EXISTS(mrt, c->mfc_parent))
index baeec29..5858574 100644 (file)
@@ -1063,10 +1063,11 @@ static unsigned int first_packet_length(struct sock *sk)
        spin_unlock_bh(&rcvq->lock);
 
        if (!skb_queue_empty(&list_kill)) {
-               lock_sock_bh(sk);
+               bool slow = lock_sock_fast(sk);
+
                __skb_queue_purge(&list_kill);
                sk_mem_reclaim_partial(sk);
-               unlock_sock_bh(sk);
+               unlock_sock_fast(sk, slow);
        }
        return res;
 }
@@ -1123,6 +1124,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        int peeked;
        int err;
        int is_udplite = IS_UDPLITE(sk);
+       bool slow;
 
        /*
         *      Check any passed addresses
@@ -1197,10 +1199,10 @@ out:
        return err;
 
 csum_copy_err:
-       lock_sock_bh(sk);
+       slow = lock_sock_fast(sk);
        if (!skb_kill_datagram(sk, skb, flags))
                UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
-       unlock_sock_bh(sk);
+       unlock_sock_fast(sk, slow);
 
        if (noblock)
                return -EAGAIN;
@@ -1625,9 +1627,9 @@ int udp_rcv(struct sk_buff *skb)
 
 void udp_destroy_sock(struct sock *sk)
 {
-       lock_sock_bh(sk);
+       bool slow = lock_sock_fast(sk);
        udp_flush_pending_frames(sk);
-       unlock_sock_bh(sk);
+       unlock_sock_fast(sk, slow);
 }
 
 /*
index cd963f6..89425af 100644 (file)
@@ -507,7 +507,7 @@ int ip6_forward(struct sk_buff *skb)
        if (mtu < IPV6_MIN_MTU)
                mtu = IPV6_MIN_MTU;
 
-       if (skb->len > mtu) {
+       if (skb->len > mtu && !skb_is_gso(skb)) {
                /* Again, force OUTPUT device used as source address */
                skb->dev = dst->dev;
                icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
index bd9e7d3..073071f 100644 (file)
@@ -2017,7 +2017,7 @@ static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
        struct rtattr *mp_head;
 
        /* If cache is unresolved, don't try to parse IIF and OIF */
-       if (c->mf6c_parent > MAXMIFS)
+       if (c->mf6c_parent >= MAXMIFS)
                return -ENOENT;
 
        if (MIF_EXISTS(mrt, c->mf6c_parent))
index 3d7a2c0..87be586 100644 (file)
@@ -328,6 +328,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
        int err;
        int is_udplite = IS_UDPLITE(sk);
        int is_udp4;
+       bool slow;
 
        if (addr_len)
                *addr_len=sizeof(struct sockaddr_in6);
@@ -424,7 +425,7 @@ out:
        return err;
 
 csum_copy_err:
-       lock_sock_bh(sk);
+       slow = lock_sock_fast(sk);
        if (!skb_kill_datagram(sk, skb, flags)) {
                if (is_udp4)
                        UDP_INC_STATS_USER(sock_net(sk),
@@ -433,7 +434,7 @@ csum_copy_err:
                        UDP6_INC_STATS_USER(sock_net(sk),
                                        UDP_MIB_INERRORS, is_udplite);
        }
-       unlock_sock_bh(sk);
+       unlock_sock_fast(sk, slow);
 
        if (flags & MSG_DONTWAIT)
                return -EAGAIN;
index c8b4599..9637e45 100644 (file)
@@ -1619,7 +1619,7 @@ static void iucv_callback_rx(struct iucv_path *path, struct iucv_message *msg)
 save_message:
        save_msg = kzalloc(sizeof(struct sock_msg_q), GFP_ATOMIC | GFP_DMA);
        if (!save_msg)
-               return;
+               goto out_unlock;
        save_msg->path = path;
        save_msg->msg = *msg;
 
index d7920d9..859d9fd 100644 (file)
@@ -76,7 +76,7 @@ tee_tg_route4(struct sk_buff *skb, const struct xt_tee_tginfo *info)
        if (ip_route_output_key(net, &rt, &fl) != 0)
                return false;
 
-       dst_release(skb_dst(skb));
+       skb_dst_drop(skb);
        skb_dst_set(skb, &rt->u.dst);
        skb->dev      = rt->u.dst.dev;
        skb->protocol = htons(ETH_P_IP);
@@ -157,7 +157,7 @@ tee_tg_route6(struct sk_buff *skb, const struct xt_tee_tginfo *info)
        if (dst == NULL)
                return false;
 
-       dst_release(skb_dst(skb));
+       skb_dst_drop(skb);
        skb_dst_set(skb, dst);
        skb->dev      = dst->dev;
        skb->protocol = htons(ETH_P_IPV6);