int (*open) (struct inode *, struct file *);
        int (*flush) (struct file *);
        int (*release) (struct inode *, struct file *);
-       int (*fsync) (struct file *, int datasync);
+       int (*fsync) (struct file *, loff_t start, loff_t end, int datasync);
        int (*aio_fsync) (struct kiocb *, int datasync);
        int (*fasync) (int, struct file *, int);
        int (*lock) (struct file *, int, struct file_lock *);
 
 locking rules:
        All may block except for ->setlease.
-       No VFS locks held on entry except for ->fsync and ->setlease.
-
-->fsync() has i_mutex on inode.
+       No VFS locks held on entry except for ->setlease.
 
 ->setlease has the file_list_lock held and must not sleep.
 
 
 offset is less than i_size and SEEK_DATA is specified, return the same offset.
 If the above is true for the offset and you are given SEEK_HOLE, return the end
 of the file.  If the offset is i_size or greater return -ENXIO in either case.
+
+[mandatory]
+       If you have your own ->fsync() you must make sure to call
+filemap_write_and_wait_range() so that all dirty pages are synced out properly.
+You must also keep in mind that ->fsync() is not called with i_mutex held
+anymore, so if you require i_mutex locking you must make sure to take it and
+release it yourself.
 
        int (*open) (struct inode *, struct file *);
        int (*flush) (struct file *);
        int (*release) (struct inode *, struct file *);
-       int (*fsync) (struct file *, int datasync);
+       int (*fsync) (struct file *, loff_t, loff_t, int datasync);
        int (*aio_fsync) (struct kiocb *, int datasync);
        int (*fasync) (int, struct file *, int);
        int (*lock) (struct file *, int, struct file_lock *);
 
        return ret;
 }
 
-static int spufs_mfc_fsync(struct file *file, int datasync)
+static int spufs_mfc_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
-       return spufs_mfc_flush(file, NULL);
+       struct inode *inode = file->f_path.dentry->d_inode;
+       int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (!err) {
+               mutex_lock(&inode->i_mutex);
+               err = spufs_mfc_flush(file, NULL);
+               mutex_unlock(&inode->i_mutex);
+       }
+       return err;
 }
 
 static int spufs_mfc_fasync(int fd, struct file *file, int on)
 
        return ps3flash_writeback(ps3flash_dev);
 }
 
-static int ps3flash_fsync(struct file *file, int datasync)
+static int ps3flash_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
-       return ps3flash_writeback(ps3flash_dev);
+       struct inode *inode = file->f_path.dentry->d_inode;
+       int err;
+       mutex_lock(&inode->i_mutex);
+       err = ps3flash_writeback(ps3flash_dev);
+       mutex_unlock(&inode->i_mutex);
+       return err;
 }
 
 static irqreturn_t ps3flash_interrupt(int irq, void *data)
 
        return new_offset;
 }
 
-static int vol_cdev_fsync(struct file *file, int datasync)
+static int vol_cdev_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
        struct ubi_volume_desc *desc = file->private_data;
        struct ubi_device *ubi = desc->vol->ubi;
-
-       return ubi_sync(ubi->ubi_num);
+       struct inode *inode = file->f_path.dentry->d_inode;
+       int err;
+       mutex_lock(&inode->i_mutex);
+       err = ubi_sync(ubi->ubi_num);
+       mutex_unlock(&inode->i_mutex);
+       return err;
 }
 
 
 
 /*
  * We want fsync() to work on POHMELFS.
  */
-static int pohmelfs_fsync(struct file *file, int datasync)
+static int pohmelfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
        struct inode *inode = file->f_mapping->host;
-
-       return sync_inode_metadata(inode, 1);
+       int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (!err) {
+               mutex_lock(&inode->i_mutex);
+               err = sync_inode_metadata(inode, 1);
+               mutex_unlock(&inode->i_mutex);
+       }
+       return err;
 }
 
 ssize_t pohmelfs_write(struct file *file, const char __user *buf,
 
 }
 
 static int
-printer_fsync(struct file *fd, int datasync)
+printer_fsync(struct file *fd, loff_t start, loff_t end, int datasync)
 {
        struct printer_dev      *dev = fd->private_data;
+       struct inode *inode = fd->f_path.dentry->d_inode;
        unsigned long           flags;
        int                     tx_list_empty;
 
+       mutex_lock(&inode->i_mutex);
        spin_lock_irqsave(&dev->lock, flags);
        tx_list_empty = (likely(list_empty(&dev->tx_reqs)));
        spin_unlock_irqrestore(&dev->lock, flags);
                wait_event_interruptible(dev->tx_flush_wait,
                                (likely(list_empty(&dev->tx_reqs_active))));
        }
+       mutex_unlock(&inode->i_mutex);
 
        return 0;
 }
 
        return 0;
 }
 
-int fb_deferred_io_fsync(struct file *file, int datasync)
+int fb_deferred_io_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
        struct fb_info *info = file->private_data;
+       struct inode *inode = file->f_path.dentry->d_inode;
+       int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (err)
+               return err;
 
        /* Skip if deferred io is compiled-in but disabled on this fbdev */
        if (!info->fbdefio)
                return 0;
 
+       mutex_lock(&inode->i_mutex);
        /* Kill off the delayed work */
        cancel_delayed_work_sync(&info->deferred_work);
 
        /* Run it immediately */
-       return schedule_delayed_work(&info->deferred_work, 0);
+       err = schedule_delayed_work(&info->deferred_work, 0);
+       mutex_unlock(&inode->i_mutex);
+       return err;
 }
 EXPORT_SYMBOL_GPL(fb_deferred_io_fsync);
 
 
 ssize_t v9fs_fid_readn(struct p9_fid *, char *, char __user *, u32, u64);
 void v9fs_blank_wstat(struct p9_wstat *wstat);
 int v9fs_vfs_setattr_dotl(struct dentry *, struct iattr *);
-int v9fs_file_fsync_dotl(struct file *filp, int datasync);
+int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end,
+                        int datasync);
 ssize_t v9fs_file_write_internal(struct inode *, struct p9_fid *,
                                 const char __user *, size_t, loff_t *, int);
 int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode);
 
 }
 
 
-static int v9fs_file_fsync(struct file *filp, int datasync)
+static int v9fs_file_fsync(struct file *filp, loff_t start, loff_t end,
+                          int datasync)
 {
        struct p9_fid *fid;
+       struct inode *inode = filp->f_mapping->host;
        struct p9_wstat wstat;
        int retval;
 
+       retval = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (retval)
+               return retval;
+
+       mutex_lock(&inode->i_mutex);
        P9_DPRINTK(P9_DEBUG_VFS, "filp %p datasync %x\n", filp, datasync);
 
        fid = filp->private_data;
        v9fs_blank_wstat(&wstat);
 
        retval = p9_client_wstat(fid, &wstat);
+       mutex_unlock(&inode->i_mutex);
+
        return retval;
 }
 
-int v9fs_file_fsync_dotl(struct file *filp, int datasync)
+int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end,
+                        int datasync)
 {
        struct p9_fid *fid;
+       struct inode *inode = filp->f_mapping->host;
        int retval;
 
+       retval = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (retval)
+               return retval;
+
+       mutex_lock(&inode->i_mutex);
        P9_DPRINTK(P9_DEBUG_VFS, "v9fs_file_fsync_dotl: filp %p datasync %x\n",
                        filp, datasync);
 
        fid = filp->private_data;
 
        retval = p9_client_fsync(fid, datasync);
+       mutex_unlock(&inode->i_mutex);
+
        return retval;
 }
 
 
 
 void           affs_free_prealloc(struct inode *inode);
 extern void    affs_truncate(struct inode *);
-int            affs_file_fsync(struct file *, int);
+int            affs_file_fsync(struct file *, loff_t, loff_t, int);
 
 /* dir.c */
 
 
        affs_free_prealloc(inode);
 }
 
-int affs_file_fsync(struct file *filp, int datasync)
+int affs_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
 {
        struct inode *inode = filp->f_mapping->host;
        int ret, err;
 
+       err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (err)
+               return err;
+
+       mutex_lock(&inode->i_mutex);
        ret = write_inode_now(inode, 0);
        err = sync_blockdev(inode->i_sb->s_bdev);
        if (!ret)
                ret = err;
+       mutex_unlock(&inode->i_mutex);
        return ret;
 }
 
 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 *, int);
+extern int afs_fsync(struct file *, loff_t, loff_t, int);
 
 
 /*****************************************************************************/
 
  * - 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, int datasync)
+int afs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
        struct dentry *dentry = file->f_path.dentry;
+       struct inode *inode = file->f_mapping->host;
        struct afs_writeback *wb, *xwb;
        struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
        int ret;
               vnode->fid.vid, vnode->fid.vnode, dentry->d_name.name,
               datasync);
 
+       ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (ret)
+               return ret;
+       mutex_lock(&inode->i_mutex);
+
        /* use a writeback record as a marker in the queue - when this reaches
         * the front of the queue, all the outstanding writes are either
         * completed or rejected */
        wb = kzalloc(sizeof(*wb), GFP_KERNEL);
-       if (!wb)
-               return -ENOMEM;
+       if (!wb) {
+               ret = -ENOMEM;
+               goto out;
+       }
        wb->vnode = vnode;
        wb->first = 0;
        wb->last = -1;
        if (ret < 0) {
                afs_put_writeback(wb);
                _leave(" = %d [wb]", ret);
-               return ret;
+               goto out;
        }
 
        /* wait for the preceding writes to actually complete */
                                       vnode->writebacks.next == &wb->link);
        afs_put_writeback(wb);
        _leave(" = %d", ret);
+out:
+       mutex_unlock(&inode->i_mutex);
        return ret;
 }
 
 
        return -EIO;
 }
 
-static int bad_file_fsync(struct file *file, int datasync)
+static int bad_file_fsync(struct file *file, loff_t start, loff_t end,
+                         int datasync)
 {
        return -EIO;
 }
 
        return retval;
 }
        
-int blkdev_fsync(struct file *filp, int datasync)
+int blkdev_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
 {
        struct inode *bd_inode = filp->f_mapping->host;
        struct block_device *bdev = I_BDEV(bd_inode);
         * i_mutex and doing so causes performance issues with concurrent
         * O_SYNC writers to a block device.
         */
-       mutex_unlock(&bd_inode->i_mutex);
-
        error = blkdev_issue_flush(bdev, GFP_KERNEL, NULL);
        if (error == -EOPNOTSUPP)
                error = 0;
 
-       mutex_lock(&bd_inode->i_mutex);
-
        return error;
 }
 EXPORT_SYMBOL(blkdev_fsync);
 
 int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
                           struct inode *inode);
 int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info);
-int btrfs_sync_file(struct file *file, int datasync);
+int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync);
 int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
                            int skip_pinned);
 extern const struct file_operations btrfs_file_operations;
 
  * 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, int datasync)
+int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 {
        struct dentry *dentry = file->f_path.dentry;
        struct inode *inode = dentry->d_inode;
 
        trace_btrfs_sync_file(file, datasync);
 
+       ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (ret)
+               return ret;
+       mutex_lock(&inode->i_mutex);
+
        /* we wait first, since the writeback may change the inode */
        root->log_batch++;
-       /* the VFS called filemap_fdatawrite for us */
        btrfs_wait_ordered_range(inode, 0, (u64)-1);
        root->log_batch++;
 
         * check the transaction that last modified this inode
         * and see if its already been committed
         */
-       if (!BTRFS_I(inode)->last_trans)
+       if (!BTRFS_I(inode)->last_trans) {
+               mutex_unlock(&inode->i_mutex);
                goto out;
+       }
 
        /*
         * if the last transaction that changed this file was before
        if (BTRFS_I(inode)->last_trans <=
            root->fs_info->last_trans_committed) {
                BTRFS_I(inode)->last_trans = 0;
+               mutex_unlock(&inode->i_mutex);
                goto out;
        }
 
        trans = btrfs_start_transaction(root, 0);
        if (IS_ERR(trans)) {
                ret = PTR_ERR(trans);
+               mutex_unlock(&inode->i_mutex);
                goto out;
        }
 
        ret = btrfs_log_dentry_safe(trans, root, dentry);
-       if (ret < 0)
+       if (ret < 0) {
+               mutex_unlock(&inode->i_mutex);
                goto out;
+       }
 
        /* we've logged all the items and now have a consistent
         * version of the file in the log.  It is possible that
         * file again, but that will end up using the synchronization
         * inside btrfs_sync_log to keep things safe.
         */
-       mutex_unlock(&dentry->d_inode->i_mutex);
+       mutex_unlock(&inode->i_mutex);
 
        if (ret != BTRFS_NO_LOG_SYNC) {
                if (ret > 0) {
        } else {
                ret = btrfs_end_transaction(trans, root);
        }
-       mutex_lock(&dentry->d_inode->i_mutex);
 out:
        return ret > 0 ? -EIO : ret;
 }
 
        spin_unlock(&ci->i_unsafe_lock);
 }
 
-int ceph_fsync(struct file *file, int datasync)
+int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
        struct inode *inode = file->f_mapping->host;
        struct ceph_inode_info *ci = ceph_inode(inode);
        dout("fsync %p%s\n", inode, datasync ? " datasync" : "");
        sync_write_wait(inode);
 
-       ret = filemap_write_and_wait(inode->i_mapping);
+       ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
        if (ret < 0)
                return ret;
+       mutex_lock(&inode->i_mutex);
 
        dirty = try_flush_caps(inode, NULL, &flush_tid);
        dout("fsync dirty caps are %s\n", ceph_cap_string(dirty));
        }
 
        dout("fsync %p%s done\n", inode, datasync ? " datasync" : "");
+       mutex_unlock(&inode->i_mutex);
        return ret;
 }
 
 
  * an fsync() on a dir will wait for any uncommitted directory
  * operations to commit.
  */
-static int ceph_dir_fsync(struct file *file, int datasync)
+static int ceph_dir_fsync(struct file *file, loff_t start, loff_t end,
+                         int datasync)
 {
        struct inode *inode = file->f_path.dentry->d_inode;
        struct ceph_inode_info *ci = ceph_inode(inode);
        int ret = 0;
 
        dout("dir_fsync %p\n", inode);
+       ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (ret)
+               return ret;
+       mutex_lock(&inode->i_mutex);
+
        spin_lock(&ci->i_unsafe_lock);
        if (list_empty(head))
                goto out;
        } while (req->r_tid < last_tid);
 out:
        spin_unlock(&ci->i_unsafe_lock);
+       mutex_unlock(&inode->i_mutex);
+
        return ret;
 }
 
 
 
 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, int datasync);
+extern int ceph_fsync(struct file *file, loff_t start, loff_t end,
+                     int datasync);
 extern void ceph_kick_flushing_caps(struct ceph_mds_client *mdsc,
                                    struct ceph_mds_session *session);
 extern struct ceph_cap *ceph_get_cap_for_mds(struct ceph_inode_info *ci,
 
 extern ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
                                  unsigned long nr_segs, loff_t pos);
 extern int cifs_lock(struct file *, int, struct file_lock *);
-extern int cifs_fsync(struct file *, int);
-extern int cifs_strict_fsync(struct file *, int);
+extern int cifs_fsync(struct file *, loff_t, loff_t, int);
+extern int cifs_strict_fsync(struct file *, loff_t, loff_t, int);
 extern int cifs_flush(struct file *, fl_owner_t id);
 extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
 extern int cifs_file_strict_mmap(struct file * , struct vm_area_struct *);
 
        return rc;
 }
 
-int cifs_strict_fsync(struct file *file, int datasync)
+int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
+                     int datasync)
 {
        int xid;
        int rc = 0;
        struct inode *inode = file->f_path.dentry->d_inode;
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
 
+       rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (rc)
+               return rc;
+       mutex_lock(&inode->i_mutex);
+
        xid = GetXid();
 
        cFYI(1, "Sync file - name: %s datasync: 0x%x",
                rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
 
        FreeXid(xid);
+       mutex_unlock(&inode->i_mutex);
        return rc;
 }
 
-int cifs_fsync(struct file *file, int datasync)
+int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
        int xid;
        int rc = 0;
        struct cifs_tcon *tcon;
        struct cifsFileInfo *smbfile = file->private_data;
        struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
+       struct inode *inode = file->f_mapping->host;
+
+       rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (rc)
+               return rc;
+       mutex_lock(&inode->i_mutex);
 
        xid = GetXid();
 
                rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
 
        FreeXid(xid);
+       mutex_unlock(&inode->i_mutex);
        return rc;
 }
 
 
 
 void coda_destroy_inodecache(void);
 int coda_init_inodecache(void);
-int coda_fsync(struct file *coda_file, int datasync);
+int coda_fsync(struct file *coda_file, loff_t start, loff_t end, int datasync);
 void coda_sysctl_init(void);
 void coda_sysctl_clean(void);
 
 
        return 0;
 }
 
-int coda_fsync(struct file *coda_file, int datasync)
+int coda_fsync(struct file *coda_file, loff_t start, loff_t end, int datasync)
 {
        struct file *host_file;
        struct inode *coda_inode = coda_file->f_path.dentry->d_inode;
              S_ISLNK(coda_inode->i_mode)))
                return -EINVAL;
 
+       err = filemap_write_and_wait_range(coda_inode->i_mapping, start, end);
+       if (err)
+               return err;
+       mutex_lock(&coda_inode->i_mutex);
+
        cfi = CODA_FTOC(coda_file);
        BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
        host_file = cfi->cfi_container;
        err = vfs_fsync(host_file, datasync);
        if (!err && !datasync)
                err = venus_fsync(coda_inode->i_sb, coda_i2f(coda_inode));
+       mutex_unlock(&coda_inode->i_mutex);
 
        return err;
 }
 
 }
 
 static int
-ecryptfs_fsync(struct file *file, int datasync)
+ecryptfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
        int rc = 0;
 
-       rc = generic_file_fsync(file, datasync);
+       rc = generic_file_fsync(file, start, end, datasync);
        if (rc)
                goto out;
-       rc = vfs_fsync(ecryptfs_file_to_lower(file), datasync);
+       rc = vfs_fsync_range(ecryptfs_file_to_lower(file), start, end,
+                            datasync);
 out:
        return rc;
 }
 
  *   Note, in exofs all metadata is written as part of inode, regardless.
  *   The writeout is synchronous
  */
-static int exofs_file_fsync(struct file *filp, int datasync)
+static int exofs_file_fsync(struct file *filp, loff_t start, loff_t end,
+                           int datasync)
 {
+       struct inode *inode = filp->f_mapping->host;
        int ret;
 
+       ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (ret)
+               return ret;
+
+       mutex_lock(&inode->i_mutex);
        ret = sync_inode_metadata(filp->f_mapping->host, 1);
+       mutex_unlock(&inode->i_mutex);
        return ret;
 }
 
 
 extern const struct file_operations ext2_dir_operations;
 
 /* file.c */
-extern int ext2_fsync(struct file *file, int datasync);
+extern int ext2_fsync(struct file *file, loff_t start, loff_t end,
+                     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;
 
        return 0;
 }
 
-int ext2_fsync(struct file *file, int datasync)
+int ext2_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
        int ret;
        struct super_block *sb = file->f_mapping->host->i_sb;
        struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
 
-       ret = generic_file_fsync(file, datasync);
+       ret = generic_file_fsync(file, start, end, 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__,
 
  * inode to disk.
  */
 
-int ext3_sync_file(struct file *file, int datasync)
+int ext3_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 {
        struct inode *inode = file->f_mapping->host;
        struct ext3_inode_info *ei = EXT3_I(inode);
        if (inode->i_sb->s_flags & MS_RDONLY)
                return 0;
 
+       ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (ret)
+               return ret;
+
+       /*
+        * Taking the mutex here just to keep consistent with how fsync was
+        * called previously, however it looks like we don't need to take
+        * i_mutex at all.
+        */
+       mutex_lock(&inode->i_mutex);
+
        J_ASSERT(ext3_journal_current_handle() == NULL);
 
        /*
         *  (they were dirtied by commit).  But that's OK - the blocks are
         *  safe in-journal, which is all fsync() needs to ensure.
         */
-       if (ext3_should_journal_data(inode))
+       if (ext3_should_journal_data(inode)) {
+               mutex_unlock(&inode->i_mutex);
                return ext3_force_commit(inode->i_sb);
+       }
 
        if (datasync)
                commit_tid = atomic_read(&ei->i_datasync_tid);
         */
        if (needs_barrier)
                blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
+       mutex_unlock(&inode->i_mutex);
        return ret;
 }
 
 extern void ext4_htree_free_dir_info(struct dir_private_info *p);
 
 /* fsync.c */
-extern int ext4_sync_file(struct file *, int);
+extern int ext4_sync_file(struct file *, loff_t, loff_t, int);
 extern int ext4_flush_completed_IO(struct inode *);
 
 /* hash.c */
 
        return ret;
 }
 
+/**
+ * __sync_file - generic_file_fsync without the locking and filemap_write
+ * @inode:     inode to sync
+ * @datasync:  only sync essential metadata if true
+ *
+ * This is just generic_file_fsync without the locking.  This is needed for
+ * nojournal mode to make sure this inodes data/metadata makes it to disk
+ * properly.  The i_mutex should be held already.
+ */
+static int __sync_inode(struct inode *inode, int datasync)
+{
+       int err;
+       int ret;
+
+       ret = sync_mapping_buffers(inode->i_mapping);
+       if (!(inode->i_state & I_DIRTY))
+               return ret;
+       if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
+               return ret;
+
+       err = sync_inode_metadata(inode, 1);
+       if (ret == 0)
+               ret = err;
+       return ret;
+}
+
 /*
  * akpm: A new design for ext4_sync_file().
  *
  * i_mutex lock is held when entering and exiting this function
  */
 
-int ext4_sync_file(struct file *file, int datasync)
+int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 {
        struct inode *inode = file->f_mapping->host;
        struct ext4_inode_info *ei = EXT4_I(inode);
 
        trace_ext4_sync_file_enter(file, datasync);
 
+       ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (ret)
+               return ret;
+       mutex_lock(&inode->i_mutex);
+
        if (inode->i_sb->s_flags & MS_RDONLY)
-               return 0;
+               goto out;
 
        ret = ext4_flush_completed_IO(inode);
        if (ret < 0)
                goto out;
 
        if (!journal) {
-               ret = generic_file_fsync(file, datasync);
+               ret = __sync_inode(inode, datasync);
                if (!ret && !list_empty(&inode->i_dentry))
                        ret = ext4_sync_parent(inode);
                goto out;
        if (needs_barrier)
                blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
  out:
+       mutex_unlock(&inode->i_mutex);
        trace_ext4_sync_file_exit(inode, ret);
        return ret;
 }
 
 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, int datasync);
+extern int fat_file_fsync(struct file *file, loff_t start, loff_t end,
+                         int datasync);
 
 /* fat/inode.c */
 extern void fat_attach(struct inode *inode, loff_t i_pos);
 
        return 0;
 }
 
-int fat_file_fsync(struct file *filp, int datasync)
+int fat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
 {
        struct inode *inode = filp->f_mapping->host;
        int res, err;
 
-       res = generic_file_fsync(filp, datasync);
+       res = generic_file_fsync(filp, start, end, datasync);
        err = sync_mapping_buffers(MSDOS_SB(inode->i_sb)->fat_inode->i_mapping);
 
        return res ? res : err;
 
        return 0;
 }
 
-static int fuse_dir_fsync(struct file *file, int datasync)
+static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
+                         int datasync)
 {
-       return fuse_fsync_common(file, datasync, 1);
+       return fuse_fsync_common(file, start, end, datasync, 1);
 }
 
 static bool update_mtime(unsigned ivalid)
 
        fuse_release_nowrite(inode);
 }
 
-int fuse_fsync_common(struct file *file, int datasync, int isdir)
+int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
+                     int datasync, int isdir)
 {
        struct inode *inode = file->f_mapping->host;
        struct fuse_conn *fc = get_fuse_conn(inode);
        if (is_bad_inode(inode))
                return -EIO;
 
+       err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (err)
+               return err;
+
        if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
                return 0;
 
+       mutex_lock(&inode->i_mutex);
+
        /*
         * Start writeback against all dirty pages of the inode, then
         * wait for all outstanding writes, before sending the FSYNC
         */
        err = write_inode_now(inode, 0);
        if (err)
-               return err;
+               goto out;
 
        fuse_sync_writes(inode);
 
        req = fuse_get_req(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
+       if (IS_ERR(req)) {
+               err = PTR_ERR(req);
+               goto out;
+       }
 
        memset(&inarg, 0, sizeof(inarg));
        inarg.fh = ff->fh;
                        fc->no_fsync = 1;
                err = 0;
        }
+out:
+       mutex_unlock(&inode->i_mutex);
        return err;
 }
 
-static int fuse_fsync(struct file *file, int datasync)
+static int fuse_fsync(struct file *file, loff_t start, loff_t end,
+                     int datasync)
 {
-       return fuse_fsync_common(file, datasync, 0);
+       return fuse_fsync_common(file, start, end, datasync, 0);
 }
 
 void fuse_read_fill(struct fuse_req *req, struct file *file, loff_t pos,
 
 /**
  * Send FSYNC or FSYNCDIR request
  */
-int fuse_fsync_common(struct file *file, int datasync, int isdir);
+int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
+                     int datasync, int isdir);
 
 /**
  * Notify poll wakeup
 
 
 /**
  * gfs2_fsync - sync the dirty data for a file (across the cluster)
- * @file: the file that points to the dentry (we ignore this)
+ * @file: the file that points to the dentry
+ * @start: the start position in the file to sync
+ * @end: the end position in the file to sync
  * @datasync: set if we can ignore timestamp changes
  *
  * The VFS will flush data for us. We only need to worry
  * Returns: errno
  */
 
-static int gfs2_fsync(struct file *file, int datasync)
+static int gfs2_fsync(struct file *file, loff_t start, loff_t end,
+                     int datasync)
 {
        struct inode *inode = file->f_mapping->host;
        int sync_state = inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC);
        struct gfs2_inode *ip = GFS2_I(inode);
        int ret;
 
+       ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (ret)
+               return ret;
+       mutex_lock(&inode->i_mutex);
+
        if (datasync)
                sync_state &= ~I_DIRTY_SYNC;
 
        if (sync_state) {
                ret = sync_inode_metadata(inode, 1);
-               if (ret)
+               if (ret) {
+                       mutex_unlock(&inode->i_mutex);
                        return ret;
+               }
                gfs2_ail_flush(ip->i_gl);
        }
 
+       mutex_unlock(&inode->i_mutex);
        return 0;
 }
 
 
        return 0;
 }
 
-static int hfs_file_fsync(struct file *filp, int datasync)
+static int hfs_file_fsync(struct file *filp, loff_t start, loff_t end,
+                         int datasync)
 {
        struct inode *inode = filp->f_mapping->host;
        struct super_block * sb;
        int ret, err;
 
+       ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (ret)
+               return ret;
+       mutex_lock(&inode->i_mutex);
+
        /* sync the inode to buffers */
        ret = write_inode_now(inode, 0);
 
        err = sync_blockdev(sb->s_bdev);
        if (!ret)
                ret = err;
+       mutex_unlock(&inode->i_mutex);
        return ret;
 }
 
 
 int hfsplus_cat_write_inode(struct inode *);
 struct inode *hfsplus_new_inode(struct super_block *, int);
 void hfsplus_delete_inode(struct inode *);
-int hfsplus_file_fsync(struct file *file, int datasync);
+int hfsplus_file_fsync(struct file *file, loff_t start, loff_t end,
+                      int datasync);
 
 /* ioctl.c */
 long hfsplus_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
 
        return 0;
 }
 
-int hfsplus_file_fsync(struct file *file, int datasync)
+int hfsplus_file_fsync(struct file *file, loff_t start, loff_t end,
+                      int datasync)
 {
        struct inode *inode = file->f_mapping->host;
        struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
        struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
        int error = 0, error2;
 
+       error = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (error)
+               return error;
+       mutex_lock(&inode->i_mutex);
+
        /*
         * Sync inode metadata into the catalog and extent trees.
         */
        if (!test_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags))
                blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
 
+       mutex_unlock(&inode->i_mutex);
+
        return error;
 }
 
 
        return 0;
 }
 
-int hostfs_fsync(struct file *file, int datasync)
+int hostfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
-       return fsync_file(HOSTFS_I(file->f_mapping->host)->fd, datasync);
+       struct inode *inode = file->f_mapping->host;
+       int ret;
+
+       ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (ret)
+               return ret;
+
+       mutex_lock(&inode->i_mutex);
+       ret = fsync_file(HOSTFS_I(inode)->fd, datasync);
+       mutex_unlock(&inode->i_mutex);
+
+       return ret;
 }
 
 static const struct file_operations hostfs_file_fops = {
 
        return 0;
 }
 
-int hpfs_file_fsync(struct file *file, int datasync)
+int hpfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
        struct inode *inode = file->f_mapping->host;
+       int ret;
+
+       ret = filemap_write_and_wait_range(file->f_mapping, start, end);
+       if (ret)
+               return ret;
        return sync_blockdev(inode->i_sb->s_bdev);
 }
 
 
 
 /* file.c */
 
-int hpfs_file_fsync(struct file *, int);
+int hpfs_file_fsync(struct file *, loff_t, loff_t, 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;
 
        return err;
 }
 
-static int hppfs_fsync(struct file *file, int datasync)
+static int hppfs_fsync(struct file *file, loff_t start, loff_t end,
+                      int datasync)
 {
-       return 0;
+       return filemap_write_and_wait_range(file->f_mapping, start, end);
 }
 
 static const struct file_operations hppfs_dir_fops = {
 
                        struct page **pagep, void **fsdata);
 static int jffs2_readpage (struct file *filp, struct page *pg);
 
-int jffs2_fsync(struct file *filp, int datasync)
+int jffs2_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
 {
        struct inode *inode = filp->f_mapping->host;
        struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
+       int ret;
+
+       ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (ret)
+               return ret;
 
+       mutex_lock(&inode->i_mutex);
        /* Trigger GC to flush any pending writes for this inode */
        jffs2_flush_wbuf_gc(c, inode->i_ino);
+       mutex_unlock(&inode->i_mutex);
 
        return 0;
 }
 
 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 *, int);
+int jffs2_fsync(struct file *, loff_t, loff_t, int);
 int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg);
 
 /* ioctl.c */
 
 #include "jfs_acl.h"
 #include "jfs_debug.h"
 
-int jfs_fsync(struct file *file, int datasync)
+int jfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
        struct inode *inode = file->f_mapping->host;
        int rc = 0;
 
+       rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (rc)
+               return rc;
+
+       mutex_lock(&inode->i_mutex);
        if (!(inode->i_state & I_DIRTY) ||
            (datasync && !(inode->i_state & I_DIRTY_DATASYNC))) {
                /* Make sure committed changes hit the disk */
                jfs_flush_journal(JFS_SBI(inode->i_sb)->log, 1);
+               mutex_unlock(&inode->i_mutex);
                return rc;
        }
 
        rc |= jfs_commit_inode(inode, 1);
+       mutex_unlock(&inode->i_mutex);
 
        return rc ? -EIO : 0;
 }
 
 struct fid;
 
 extern struct inode *ialloc(struct inode *, umode_t);
-extern int jfs_fsync(struct file *, int);
+extern int jfs_fsync(struct file *, loff_t, loff_t, 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);
 
  * 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)
+int generic_file_fsync(struct file *file, loff_t start, loff_t end,
+                      int datasync)
 {
        struct inode *inode = file->f_mapping->host;
        int err;
        int ret;
 
+       err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (err)
+               return err;
+
+       mutex_lock(&inode->i_mutex);
        ret = sync_mapping_buffers(inode->i_mapping);
        if (!(inode->i_state & I_DIRTY))
-               return ret;
+               goto out;
        if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
-               return ret;
+               goto out;
 
        err = sync_inode_metadata(inode, 1);
        if (ret == 0)
                ret = err;
+out:
+       mutex_unlock(&inode->i_mutex);
        return ret;
 }
 EXPORT_SYMBOL(generic_file_fsync);
 /*
  * No-op implementation of ->fsync for in-memory filesystems.
  */
-int noop_fsync(struct file *file, int datasync)
+int noop_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
        return 0;
 }
 
        }
 }
 
-int logfs_fsync(struct file *file, int datasync)
+int logfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
        struct super_block *sb = file->f_mapping->host->i_sb;
+       struct inode *inode = file->f_mapping->host;
+       int ret;
+
+       ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (ret)
+               return ret;
 
+       mutex_lock(&inode->i_mutex);
        logfs_write_anchor(sb);
+       mutex_unlock(&inode->i_mutex);
+
        return 0;
 }
 
 
 extern const struct address_space_operations logfs_reg_aops;
 int logfs_readpage(struct file *file, struct page *page);
 long logfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-int logfs_fsync(struct file *file, int datasync);
+int logfs_fsync(struct file *file, loff_t start, loff_t end, int datasync);
 
 /* gc.c */
 u32 get_best_cand(struct super_block *sb, struct candidate_list *list, u32 *ec);
 
 
 #include "ncp_fs.h"
 
-static int ncp_fsync(struct file *file, int datasync)
+static int ncp_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
-       return 0;
+       return filemap_write_and_wait_range(file->f_mapping, start, end);
 }
 
 /*
 
 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 *, int);
+static int nfs_fsync_dir(struct file *, loff_t, loff_t, int);
 static loff_t nfs_llseek_dir(struct file *, loff_t, int);
 static void nfs_readdir_clear_array(struct page*);
 
  * All directory operations under NFS are synchronous, so fsync()
  * is a dummy operation.
  */
-static int nfs_fsync_dir(struct file *filp, int datasync)
+static int nfs_fsync_dir(struct file *filp, loff_t start, loff_t end,
+                        int datasync)
 {
        struct dentry *dentry = filp->f_path.dentry;
+       struct inode *inode = dentry->d_inode;
 
        dfprintk(FILE, "NFS: fsync dir(%s/%s) datasync %d\n",
                        dentry->d_parent->d_name.name, dentry->d_name.name,
                        datasync);
 
+       mutex_lock(&inode->i_mutex);
        nfs_inc_stats(dentry->d_inode, NFSIOS_VFSFSYNC);
+       mutex_unlock(&inode->i_mutex);
        return 0;
 }
 
 
 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 *, int datasync);
+static int  nfs_file_fsync(struct file *, loff_t, loff_t, 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);
  * fall back to doing a synchronous write.
  */
 static int
-nfs_file_fsync(struct file *file, int datasync)
+nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
        struct dentry *dentry = file->f_path.dentry;
        struct nfs_open_context *ctx = nfs_file_open_context(file);
        int have_error, status;
        int ret = 0;
 
-
        dprintk("NFS: fsync file(%s/%s) datasync %d\n",
                        dentry->d_parent->d_name.name, dentry->d_name.name,
                        datasync);
 
+       ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (ret)
+               return ret;
+       mutex_lock(&inode->i_mutex);
+
        nfs_inc_stats(inode, NFSIOS_VFSFSYNC);
        have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
        status = nfs_commit_inode(inode, FLUSH_SYNC);
        if (!ret && !datasync)
                /* application has asked for meta-data sync */
                ret = pnfs_layoutcommit_inode(inode, true);
+       mutex_unlock(&inode->i_mutex);
        return ret;
 }
 
 
 #include "nilfs.h"
 #include "segment.h"
 
-int nilfs_sync_file(struct file *file, int datasync)
+int nilfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 {
        /*
         * Called from fsync() system call
        struct inode *inode = file->f_mapping->host;
        int err;
 
-       if (!nilfs_inode_dirty(inode))
+       err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (err)
+               return err;
+       mutex_lock(&inode->i_mutex);
+
+       if (!nilfs_inode_dirty(inode)) {
+               mutex_unlock(&inode->i_mutex);
                return 0;
+       }
 
        if (datasync)
                err = nilfs_construct_dsync_segment(inode->i_sb, inode, 0,
        else
                err = nilfs_construct_segment(inode->i_sb);
 
+       mutex_unlock(&inode->i_mutex);
        return err;
 }
 
 
                           struct page *, struct inode *);
 
 /* file.c */
-extern int nilfs_sync_file(struct file *, int);
+extern int nilfs_sync_file(struct file *, loff_t, loff_t, int);
 
 /* ioctl.c */
 long nilfs_ioctl(struct file *, unsigned int, unsigned long);
 
  * 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, int datasync)
+static int ntfs_dir_fsync(struct file *filp, loff_t start, loff_t end,
+                         int datasync)
 {
        struct inode *bmp_vi, *vi = filp->f_mapping->host;
        int err, ret;
        ntfs_attr na;
 
        ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
+
+       err = filemap_write_and_wait_range(vi->i_mapping, start, end);
+       if (err)
+               return err;
+       mutex_lock(&vi->i_mutex);
+
        BUG_ON(!S_ISDIR(vi->i_mode));
        /* If the bitmap attribute inode is in memory sync it, too. */
        na.mft_no = vi->i_ino;
        else
                ntfs_warning(vi->i_sb, "Failed to f%ssync inode 0x%lx.  Error "
                                "%u.", datasync ? "data" : "", vi->i_ino, -ret);
+       mutex_unlock(&vi->i_mutex);
        return ret;
 }
 
 
  * 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, int datasync)
+static int ntfs_file_fsync(struct file *filp, loff_t start, loff_t end,
+                          int datasync)
 {
        struct inode *vi = filp->f_mapping->host;
        int err, ret = 0;
 
        ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
+
+       err = filemap_write_and_wait_range(vi->i_mapping, start, end);
+       if (err)
+               return err;
+       mutex_lock(&vi->i_mutex);
+
        BUG_ON(S_ISDIR(vi->i_mode));
        if (!datasync || !NInoNonResident(NTFS_I(vi)))
                ret = __ntfs_write_inode(vi, 1);
        else
                ntfs_warning(vi->i_sb, "Failed to f%ssync inode 0x%lx.  Error "
                                "%u.", datasync ? "data" : "", vi->i_ino, -ret);
+       mutex_unlock(&vi->i_mutex);
        return ret;
 }
 
 
        return 0;
 }
 
-static int ocfs2_sync_file(struct file *file, int datasync)
+static int ocfs2_sync_file(struct file *file, loff_t start, loff_t end,
+                          int datasync)
 {
        int err = 0;
        journal_t *journal;
                              file->f_path.dentry->d_name.name,
                              (unsigned long long)datasync);
 
+       err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (err)
+               return err;
+
+       /*
+        * Probably don't need the i_mutex at all in here, just putting it here
+        * to be consistent with how fsync used to be called, someone more
+        * familiar with the fs could possibly remove it.
+        */
+       mutex_lock(&inode->i_mutex);
        if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) {
                /*
                 * We still have to flush drive's caches to get data to the
 bail:
        if (err)
                mlog_errno(err);
+       mutex_unlock(&inode->i_mutex);
 
        return (err < 0) ? -EIO : 0;
 }
 
 extern const struct reiserfs_key MIN_KEY;
 
 static int reiserfs_readdir(struct file *, void *, filldir_t);
-static int reiserfs_dir_fsync(struct file *filp, int datasync);
+static int reiserfs_dir_fsync(struct file *filp, loff_t start, loff_t end,
+                             int datasync);
 
 const struct file_operations reiserfs_dir_operations = {
        .llseek = generic_file_llseek,
 #endif
 };
 
-static int reiserfs_dir_fsync(struct file *filp, int datasync)
+static int reiserfs_dir_fsync(struct file *filp, loff_t start, loff_t end,
+                             int datasync)
 {
        struct inode *inode = filp->f_mapping->host;
        int err;
+
+       err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (err)
+               return err;
+
+       mutex_lock(&inode->i_mutex);
        reiserfs_write_lock(inode->i_sb);
        err = reiserfs_commit_for_inode(inode);
        reiserfs_write_unlock(inode->i_sb);
+       mutex_unlock(&inode->i_mutex);
        if (err < 0)
                return err;
        return 0;
 
  * be removed...
  */
 
-static int reiserfs_sync_file(struct file *filp, int datasync)
+static int reiserfs_sync_file(struct file *filp, loff_t start, loff_t end,
+                             int datasync)
 {
        struct inode *inode = filp->f_mapping->host;
        int err;
        int barrier_done;
 
+       err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (err)
+               return err;
+
+       mutex_lock(&inode->i_mutex);
        BUG_ON(!S_ISREG(inode->i_mode));
        err = sync_mapping_buffers(inode->i_mapping);
        reiserfs_write_lock(inode->i_sb);
        reiserfs_write_unlock(inode->i_sb);
        if (barrier_done != 1 && reiserfs_barrier_flush(inode->i_sb))
                blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
+       mutex_unlock(&inode->i_mutex);
        if (barrier_done < 0)
                return barrier_done;
        return (err < 0) ? -EIO : 0;
 
  */
 int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync)
 {
-       struct address_space *mapping = file->f_mapping;
-       int err, ret;
-
-       if (!file->f_op || !file->f_op->fsync) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       ret = filemap_write_and_wait_range(mapping, start, end);
-
-       /*
-        * We need to protect against concurrent writers, which could cause
-        * livelocks in fsync_buffers_list().
-        */
-       mutex_lock(&mapping->host->i_mutex);
-       err = file->f_op->fsync(file, datasync);
-       if (!ret)
-               ret = err;
-       mutex_unlock(&mapping->host->i_mutex);
-
-out:
-       return ret;
+       if (!file->f_op || !file->f_op->fsync)
+               return -EINVAL;
+       return file->f_op->fsync(file, start, end, datasync);
 }
 EXPORT_SYMBOL(vfs_fsync_range);
 
 
        return NULL;
 }
 
-int ubifs_fsync(struct file *file, int datasync)
+int ubifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
        struct inode *inode = file->f_mapping->host;
        struct ubifs_info *c = inode->i_sb->s_fs_info;
                 */
                return 0;
 
-       /*
-        * VFS has already synchronized dirty pages for this inode. Synchronize
-        * the inode unless this is a 'datasync()' call.
-        */
+       err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (err)
+               return err;
+       mutex_lock(&inode->i_mutex);
+
+       /* Synchronize the inode unless this is a 'datasync()' call. */
        if (!datasync || (inode->i_state & I_DIRTY_DATASYNC)) {
                err = inode->i_sb->s_op->write_inode(inode, NULL);
                if (err)
-                       return err;
+                       goto out;
        }
 
        /*
         * them.
         */
        err = ubifs_sync_wbufs_by_inode(c, inode);
-       if (err)
-               return err;
-
-       return 0;
+out:
+       mutex_unlock(&inode->i_mutex);
+       return err;
 }
 
 /**
 
 int ubifs_calc_dark(const struct ubifs_info *c, int spc);
 
 /* file.c */
-int ubifs_fsync(struct file *file, int datasync);
+int ubifs_fsync(struct file *file, loff_t start, loff_t end, int datasync);
 int ubifs_setattr(struct dentry *dentry, struct iattr *attr);
 
 /* dir.c */
 
 STATIC int
 xfs_file_fsync(
        struct file             *file,
+       loff_t                  start,
+       loff_t                  end,
        int                     datasync)
 {
        struct inode            *inode = file->f_mapping->host;
 
        trace_xfs_file_fsync(ip);
 
+       error = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (error)
+               return error;
+
        if (XFS_FORCED_SHUTDOWN(mp))
                return -XFS_ERROR(EIO);
 
        /* Handle various SYNC-type writes */
        if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) {
                loff_t end = pos + ret - 1;
-               int error, error2;
 
                xfs_rw_iunlock(ip, iolock);
-               error = filemap_write_and_wait_range(mapping, pos, end);
+               ret = -xfs_file_fsync(file, pos, end,
+                                     (file->f_flags & __O_SYNC) ? 0 : 1);
                xfs_rw_ilock(ip, iolock);
-
-               error2 = -xfs_file_fsync(file,
-                                        (file->f_flags & __O_SYNC) ? 0 : 1);
-               if (error)
-                       ret = error;
-               else if (error2)
-                       ret = error2;
        }
 
 out_unlock:
 
 extern void ext3_htree_free_dir_info(struct dir_private_info *p);
 
 /* fsync.c */
-extern int ext3_sync_file(struct file *, int);
+extern int ext3_sync_file(struct file *, loff_t, loff_t, int);
 
 /* hash.c */
 extern int ext3fs_dirhash(const char *name, int len, struct
 
                                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, int datasync);
+extern int fb_deferred_io_fsync(struct file *file, loff_t start,
+                               loff_t end, int datasync);
 
 static inline bool fb_be_math(struct fb_info *info)
 {
 
        int (*open) (struct inode *, struct file *);
        int (*flush) (struct file *, fl_owner_t id);
        int (*release) (struct inode *, struct file *);
-       int (*fsync) (struct file *, int datasync);
+       int (*fsync) (struct file *, loff_t, loff_t, int datasync);
        int (*aio_fsync) (struct kiocb *, int datasync);
        int (*fasync) (int, struct file *, int);
        int (*lock) (struct file *, int, struct file_lock *);
 /* 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, int datasync);
+extern int blkdev_fsync(struct file *filp, loff_t start, loff_t end,
+                       int datasync);
 
 /* fs/splice.c */
 extern ssize_t generic_file_splice_read(struct file *, loff_t *,
 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 noop_fsync(struct file *, int);
+extern int noop_fsync(struct file *, loff_t, loff_t, 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,
 extern ssize_t simple_write_to_buffer(void *to, size_t available, loff_t *ppos,
                const void __user *from, size_t count);
 
-extern int generic_file_fsync(struct file *, int);
+extern int generic_file_fsync(struct file *, loff_t, loff_t, int);
 
 extern int generic_check_addressable(unsigned, u64);
 
 
        return 0;
 }
 
-static int shm_fsync(struct file *file, int datasync)
+static int shm_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
        struct shm_file_data *sfd = shm_file_data(file);
 
        if (!sfd->file->f_op->fsync)
                return -EINVAL;
-       return sfd->file->f_op->fsync(sfd->file, datasync);
+       return sfd->file->f_op->fsync(sfd->file, start, end, datasync);
 }
 
 static unsigned long shm_get_unmapped_area(struct file *file,