]> Git Repo - linux.git/commitdiff
Merge tag 'wberr-v4.14-1' of git://git.kernel.org/pub/scm/linux/kernel/git/jlayton...
authorLinus Torvalds <[email protected]>
Wed, 6 Sep 2017 21:11:03 +0000 (14:11 -0700)
committerLinus Torvalds <[email protected]>
Wed, 6 Sep 2017 21:11:03 +0000 (14:11 -0700)
Pull writeback error handling updates from Jeff Layton:
 "This pile continues the work from last cycle on better tracking
  writeback errors. In v4.13 we added some basic errseq_t infrastructure
  and converted a few filesystems to use it.

  This set continues refining that infrastructure, adds documentation,
  and converts most of the other filesystems to use it. The main
  exception at this point is the NFS client"

* tag 'wberr-v4.14-1' of git://git.kernel.org/pub/scm/linux/kernel/git/jlayton/linux:
  ecryptfs: convert to file_write_and_wait in ->fsync
  mm: remove optimizations based on i_size in mapping writeback waits
  fs: convert a pile of fsync routines to errseq_t based reporting
  gfs2: convert to errseq_t based writeback error reporting for fsync
  fs: convert sync_file_range to use errseq_t based error-tracking
  mm: add file_fdatawait_range and file_write_and_wait
  fuse: convert to errseq_t based error tracking for fsync
  mm: consolidate dax / non-dax checks for writeback
  Documentation: add some docs for errseq_t
  errseq: rename __errseq_set to errseq_set

1  2 
drivers/staging/lustre/lustre/llite/file.c
fs/9p/vfs_file.c
fs/f2fs/file.c
fs/fuse/file.c
fs/gfs2/file.c
include/linux/fs.h
mm/filemap.c

index 2c30e422a47eaecd5f829f454ce0ae3432b880b9,f7d07735ac6676eb9ddf86e70922b70be70cd7fb..be665454f40755b93d45400f1b402bb3b53e5556
   */
  
  #define DEBUG_SUBSYSTEM S_LLITE
 -#include "../include/lustre_dlm.h"
 +#include <lustre_dlm.h>
  #include <linux/pagemap.h>
  #include <linux/file.h>
  #include <linux/sched.h>
  #include <linux/mount.h>
 -#include "../include/lustre/ll_fiemap.h"
 -#include "../include/lustre/lustre_ioctl.h"
 -#include "../include/lustre_swab.h"
 +#include <uapi/linux/lustre/lustre_fiemap.h>
 +#include <uapi/linux/lustre/lustre_ioctl.h>
 +#include <lustre_swab.h>
  
 -#include "../include/cl_object.h"
 +#include <cl_object.h>
  #include "llite_internal.h"
  
  static int
@@@ -2364,7 -2364,7 +2364,7 @@@ int ll_fsync(struct file *file, loff_t 
               PFID(ll_inode2fid(inode)), inode);
        ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_FSYNC, 1);
  
-       rc = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       rc = file_write_and_wait_range(file, start, end);
        inode_lock(inode);
  
        /* catch async errors that were recorded back when async writeback
@@@ -3035,6 -3035,9 +3035,6 @@@ struct posix_acl *ll_get_acl(struct ino
        spin_lock(&lli->lli_lock);
        /* VFS' acl_permission_check->check_acl will release the refcount */
        acl = posix_acl_dup(lli->lli_posix_acl);
 -#ifdef CONFIG_FS_POSIX_ACL
 -      forget_cached_acl(inode, type);
 -#endif
        spin_unlock(&lli->lli_lock);
  
        return acl;
diff --combined fs/9p/vfs_file.c
index 43c242e171321b7dc8faec1561ad34846e03a18d,4802d75b3cf798143a7a44a6120402f9a2cb343b..03c9e325bfbc1f41e785d45aed5d563b778f959f
@@@ -288,7 -288,7 +288,7 @@@ static int v9fs_file_getlock(struct fil
                        fl->fl_end = OFFSET_MAX;
                else
                        fl->fl_end = glock.start + glock.length - 1;
 -              fl->fl_pid = glock.proc_id;
 +              fl->fl_pid = -glock.proc_id;
        }
        kfree(glock.client_id);
        return res;
@@@ -445,7 -445,7 +445,7 @@@ static int v9fs_file_fsync(struct file 
        struct p9_wstat wstat;
        int retval;
  
-       retval = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       retval = file_write_and_wait_range(filp, start, end);
        if (retval)
                return retval;
  
@@@ -468,7 -468,7 +468,7 @@@ int v9fs_file_fsync_dotl(struct file *f
        struct inode *inode = filp->f_mapping->host;
        int retval;
  
-       retval = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       retval = file_write_and_wait_range(filp, start, end);
        if (retval)
                return retval;
  
diff --combined fs/f2fs/file.c
index 2706130c261b060f46cb526b8e7ac501789808a7,40fb3d4bb9c256cc6060644424d18a19f1498bfb..843a0d99f7ea77b7f64b93dc0045e22c8d2e38a3
@@@ -206,7 -206,7 +206,7 @@@ static int f2fs_do_sync_file(struct fil
        /* if fdatasync is triggered, let's do in-place-update */
        if (datasync || get_dirty_pages(inode) <= SM_I(sbi)->min_fsync_blocks)
                set_inode_flag(inode, FI_NEED_IPU);
-       ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       ret = file_write_and_wait_range(file, start, end);
        clear_inode_flag(inode, FI_NEED_IPU);
  
        if (ret) {
@@@ -1538,6 -1538,7 +1538,6 @@@ static int f2fs_ioc_setflags(struct fil
  
        /* Is it quota file? Do not allow user to mess with it */
        if (IS_NOQUOTA(inode)) {
 -              inode_unlock(inode);
                ret = -EPERM;
                goto unlock_out;
        }
  
        if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
                if (!capable(CAP_LINUX_IMMUTABLE)) {
 -                      inode_unlock(inode);
                        ret = -EPERM;
 -                      goto out;
 +                      goto unlock_out;
                }
        }
  
        f2fs_mark_inode_dirty_sync(inode, false);
  unlock_out:
        inode_unlock(inode);
 -out:
        mnt_drop_write_file(filp);
        return ret;
  }
diff --combined fs/fuse/file.c
index 0273029b1220ce3aca8f389e909e29a2214dc233,e2ffc499d106c3682241a0d9badbedc54d413dfb..d6678980428782fd83bed24f2526e0caf7fbbfc1
@@@ -46,7 -46,7 +46,7 @@@ struct fuse_file *fuse_file_alloc(struc
  {
        struct fuse_file *ff;
  
 -      ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL);
 +      ff = kzalloc(sizeof(struct fuse_file), GFP_KERNEL);
        if (unlikely(!ff))
                return NULL;
  
@@@ -457,7 -457,7 +457,7 @@@ int fuse_fsync_common(struct file *file
         * wait for all outstanding writes, before sending the FSYNC
         * request.
         */
-       err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       err = file_write_and_wait_range(file, start, end);
        if (err)
                goto out;
  
  
        /*
         * Due to implementation of fuse writeback
-        * filemap_write_and_wait_range() does not catch errors.
+        * file_write_and_wait_range() does not catch errors.
         * We have to do this directly after fuse_sync_writes()
         */
-       err = filemap_check_errors(file->f_mapping);
+       err = file_check_and_advance_wb_err(file);
        if (err)
                goto out;
  
@@@ -609,7 -609,7 +609,7 @@@ static void fuse_aio_complete_req(struc
        struct fuse_io_priv *io = req->io;
        ssize_t pos = -1;
  
 -      fuse_release_user_pages(req, !io->write);
 +      fuse_release_user_pages(req, io->should_dirty);
  
        if (io->write) {
                if (req->misc.write.in.size != req->misc.write.out.size)
@@@ -1316,6 -1316,7 +1316,6 @@@ ssize_t fuse_direct_io(struct fuse_io_p
                       loff_t *ppos, int flags)
  {
        int write = flags & FUSE_DIO_WRITE;
 -      bool should_dirty = !write && iter_is_iovec(iter);
        int cuse = flags & FUSE_DIO_CUSE;
        struct file *file = io->file;
        struct inode *inode = file->f_mapping->host;
                        inode_unlock(inode);
        }
  
 +      io->should_dirty = !write && iter_is_iovec(iter);
        while (count) {
                size_t nres;
                fl_owner_t owner = current->files;
                        nres = fuse_send_read(req, io, pos, nbytes, owner);
  
                if (!io->async)
 -                      fuse_release_user_pages(req, should_dirty);
 +                      fuse_release_user_pages(req, io->should_dirty);
                if (req->out.h.error) {
                        err = req->out.h.error;
                        break;
@@@ -1669,7 -1669,6 +1669,7 @@@ err_nofile
  err_free:
        fuse_request_free(req);
  err:
 +      mapping_set_error(page->mapping, error);
        end_page_writeback(page);
        return error;
  }
@@@ -2102,11 -2101,11 +2102,11 @@@ static int convert_fuse_file_lock(struc
                fl->fl_end = ffl->end;
  
                /*
 -               * Convert pid into the caller's pid namespace. If the pid
 -               * does not map into the namespace fl_pid will get set to 0.
 +               * Convert pid into init's pid namespace.  The locks API will
 +               * translate it into the caller's pid namespace.
                 */
                rcu_read_lock();
 -              fl->fl_pid = pid_vnr(find_pid_ns(ffl->pid, fc->pid_ns));
 +              fl->fl_pid = pid_nr_ns(find_pid_ns(ffl->pid, fc->pid_ns), &init_pid_ns);
                rcu_read_unlock();
                break;
  
diff --combined fs/gfs2/file.c
index bb48074be01938614d1521b8589afccfe00f115c,c53ac6efd04c5e299d34f857697ddc81debbda14..33a0cb5701a330623ded09e427f79d53d6cee4db
@@@ -668,12 -668,14 +668,14 @@@ static int gfs2_fsync(struct file *file
                if (ret)
                        return ret;
                if (gfs2_is_jdata(ip))
-                       filemap_write_and_wait(mapping);
+                       ret = file_write_and_wait(file);
+               if (ret)
+                       return ret;
                gfs2_ail_flush(ip->i_gl, 1);
        }
  
        if (mapping->nrpages)
-               ret = filemap_fdatawait_range(mapping, start, end);
+               ret = file_fdatawait_range(file, start, end);
  
        return ret ? ret : ret1;
  }
@@@ -1030,7 -1032,8 +1032,7 @@@ static int do_flock(struct file *file, 
  
        mutex_lock(&fp->f_fl_mutex);
  
 -      gl = fl_gh->gh_gl;
 -      if (gl) {
 +      if (gfs2_holder_initialized(fl_gh)) {
                if (fl_gh->gh_state == state)
                        goto out;
                locks_lock_file_wait(file,
diff --combined include/linux/fs.h
index 0a51a8b197f7203b7462ec2da1f4226dec90c8e2,909210bd63665a0ac2e71dee09d8495184072c08..5b744a3456c5f54bf92dde75a3c5a1dbd7783b98
@@@ -72,8 -72,6 +72,8 @@@ extern int leases_enable, lease_break_t
  extern int sysctl_protected_symlinks;
  extern int sysctl_protected_hardlinks;
  
 +typedef __kernel_rwf_t rwf_t;
 +
  struct buffer_head;
  typedef int (get_block_t)(struct inode *inode, sector_t iblock,
                        struct buffer_head *bh_result, int create);
@@@ -298,7 -296,7 +298,7 @@@ struct kiocb 
        void                    *private;
        int                     ki_flags;
        enum rw_hint            ki_hint;
 -};
 +} __randomize_layout;
  
  static inline bool is_sync_kiocb(struct kiocb *kiocb)
  {
@@@ -406,7 -404,7 +406,7 @@@ struct address_space 
        struct list_head        private_list;   /* ditto */
        void                    *private_data;  /* ditto */
        errseq_t                wb_err;
 -} __attribute__((aligned(sizeof(long))));
 +} __attribute__((aligned(sizeof(long)))) __randomize_layout;
        /*
         * On most architectures that alignment is already the case; but
         * must be enforced here for CRIS, to let the least significant bit
@@@ -449,7 -447,7 +449,7 @@@ struct block_device 
        int                     bd_fsfreeze_count;
        /* Mutex for freeze */
        struct mutex            bd_fsfreeze_mutex;
 -};
 +} __randomize_layout;
  
  /*
   * Radix-tree tags, for tagging dirty and writeback pages within the pagecache
@@@ -668,7 -666,7 +668,7 @@@ struct inode 
  #endif
  
        void                    *i_private; /* fs or device private pointer */
 -};
 +} __randomize_layout;
  
  static inline unsigned int i_blocksize(const struct inode *node)
  {
@@@ -885,8 -883,7 +885,8 @@@ struct file 
  #endif /* #ifdef CONFIG_EPOLL */
        struct address_space    *f_mapping;
        errseq_t                f_wb_err;
 -} __attribute__((aligned(4)));        /* lest something weird decides that 2 is OK */
 +} __randomize_layout
 +  __attribute__((aligned(4)));        /* lest something weird decides that 2 is OK */
  
  struct file_handle {
        __u32 handle_bytes;
@@@ -909,9 -906,9 +909,9 @@@ static inline struct file *get_file(str
  /* Page cache limit. The filesystems should put that into their s_maxbytes 
     limits, otherwise bad things can happen in VM. */ 
  #if BITS_PER_LONG==32
 -#define MAX_LFS_FILESIZE      (((loff_t)PAGE_SIZE << (BITS_PER_LONG-1))-1)
 +#define MAX_LFS_FILESIZE      ((loff_t)ULONG_MAX << PAGE_SHIFT)
  #elif BITS_PER_LONG==64
 -#define MAX_LFS_FILESIZE      ((loff_t)0x7fffffffffffffffLL)
 +#define MAX_LFS_FILESIZE      ((loff_t)LLONG_MAX)
  #endif
  
  #define FL_POSIX      1
@@@ -1002,6 -999,7 +1002,6 @@@ struct file_lock 
        unsigned char fl_type;
        unsigned int fl_pid;
        int fl_link_cpu;                /* what cpu's list is this on? */
 -      struct pid *fl_nspid;
        wait_queue_head_t fl_wait;
        struct file *fl_file;
        loff_t fl_start;
                        int state;              /* state of grant or error if -ve */
                } afs;
        } fl_u;
 -};
 +} __randomize_layout;
  
  struct file_lock_context {
        spinlock_t              flc_lock;
@@@ -1414,7 -1412,7 +1414,7 @@@ struct super_block 
  
        spinlock_t              s_inode_wblist_lock;
        struct list_head        s_inodes_wb;    /* writeback inodes */
 -};
 +} __randomize_layout;
  
  /* Helper functions so that in most cases filesystems will
   * not need to deal directly with kuid_t and kgid_t and can
@@@ -1700,7 -1698,7 +1700,7 @@@ struct file_operations 
                        u64);
        ssize_t (*dedupe_file_range)(struct file *, u64, u64, struct file *,
                        u64);
 -};
 +} __randomize_layout;
  
  struct inode_operations {
        struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
@@@ -1759,9 -1757,9 +1759,9 @@@ extern ssize_t __vfs_write(struct file 
  extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *);
  extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *);
  extern ssize_t vfs_readv(struct file *, const struct iovec __user *,
 -              unsigned long, loff_t *, int);
 +              unsigned long, loff_t *, rwf_t);
  extern ssize_t vfs_writev(struct file *, const struct iovec __user *,
 -              unsigned long, loff_t *, int);
 +              unsigned long, loff_t *, rwf_t);
  extern ssize_t vfs_copy_file_range(struct file *, loff_t , struct file *,
                                   loff_t, size_t, unsigned int);
  extern int vfs_clone_file_prep_inodes(struct inode *inode_in, loff_t pos_in,
@@@ -2472,13 -2470,9 +2472,13 @@@ static inline void bd_unlink_disk_holde
  #endif
  
  /* fs/char_dev.c */
 -#define CHRDEV_MAJOR_HASH_SIZE        255
 +#define CHRDEV_MAJOR_MAX 512
  /* Marks the bottom of the first segment of free char majors */
  #define CHRDEV_MAJOR_DYN_END 234
 +/* Marks the top and bottom of the second segment of free char majors */
 +#define CHRDEV_MAJOR_DYN_EXT_START 511
 +#define CHRDEV_MAJOR_DYN_EXT_END 384
 +
  extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *);
  extern int register_chrdev_region(dev_t, unsigned, const char *);
  extern int __register_chrdev(unsigned int major, unsigned int baseminor,
@@@ -2505,14 -2499,14 +2505,14 @@@ static inline void unregister_chrdev(un
  #define BDEVT_SIZE    10      /* Largest string for MAJ:MIN for blkdev */
  
  #ifdef CONFIG_BLOCK
 -#define BLKDEV_MAJOR_HASH_SIZE        255
 +#define BLKDEV_MAJOR_MAX      512
  extern const char *__bdevname(dev_t, char *buffer);
  extern const char *bdevname(struct block_device *bdev, char *buffer);
  extern struct block_device *lookup_bdev(const char *);
  extern void blkdev_show(struct seq_file *,off_t);
  
  #else
 -#define BLKDEV_MAJOR_HASH_SIZE        0
 +#define BLKDEV_MAJOR_MAX      0
  #endif
  
  extern void init_special_inode(struct inode *, umode_t, dev_t);
@@@ -2544,12 -2538,19 +2544,19 @@@ extern int invalidate_inode_pages2_rang
  extern int write_inode_now(struct inode *, int);
  extern int filemap_fdatawrite(struct address_space *);
  extern int filemap_flush(struct address_space *);
- extern int filemap_fdatawait(struct address_space *);
  extern int filemap_fdatawait_keep_errors(struct address_space *mapping);
  extern int filemap_fdatawait_range(struct address_space *, loff_t lstart,
                                   loff_t lend);
+ static inline int filemap_fdatawait(struct address_space *mapping)
+ {
+       return filemap_fdatawait_range(mapping, 0, LLONG_MAX);
+ }
  extern bool filemap_range_has_page(struct address_space *, loff_t lstart,
                                  loff_t lend);
+ extern int __must_check file_fdatawait_range(struct file *file, loff_t lstart,
+                                               loff_t lend);
  extern int filemap_write_and_wait(struct address_space *mapping);
  extern int filemap_write_and_wait_range(struct address_space *mapping,
                                        loff_t lstart, loff_t lend);
@@@ -2558,12 -2559,19 +2565,19 @@@ extern int __filemap_fdatawrite_range(s
  extern int filemap_fdatawrite_range(struct address_space *mapping,
                                loff_t start, loff_t end);
  extern int filemap_check_errors(struct address_space *mapping);
  extern void __filemap_set_wb_err(struct address_space *mapping, int err);
+ extern int __must_check file_fdatawait_range(struct file *file, loff_t lstart,
+                                               loff_t lend);
  extern int __must_check file_check_and_advance_wb_err(struct file *file);
  extern int __must_check file_write_and_wait_range(struct file *file,
                                                loff_t start, loff_t end);
  
+ static inline int file_write_and_wait(struct file *file)
+ {
+       return file_write_and_wait_range(file, 0, LLONG_MAX);
+ }
  /**
   * filemap_set_wb_err - set a writeback error on an address_space
   * @mapping: mapping in which to set writeback error
   * When a writeback error occurs, most filesystems will want to call
   * filemap_set_wb_err to record the error in the mapping so that it will be
   * automatically reported whenever fsync is called on the file.
-  *
-  * FIXME: mention FS_* flag here?
   */
  static inline void filemap_set_wb_err(struct address_space *mapping, int err)
  {
@@@ -2836,7 -2842,6 +2848,7 @@@ static inline void lockdep_annotate_ino
  #endif
  extern void unlock_new_inode(struct inode *);
  extern unsigned int get_next_ino(void);
 +extern void evict_inodes(struct super_block *sb);
  
  extern void __iget(struct inode * inode);
  extern void iget_failed(struct inode *);
@@@ -2880,9 -2885,9 +2892,9 @@@ extern ssize_t generic_file_direct_writ
  extern ssize_t generic_perform_write(struct file *, struct iov_iter *, loff_t);
  
  ssize_t vfs_iter_read(struct file *file, struct iov_iter *iter, loff_t *ppos,
 -              int flags);
 +              rwf_t flags);
  ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos,
 -              int flags);
 +              rwf_t flags);
  
  /* fs/block_dev.c */
  extern ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to);
@@@ -3149,7 -3154,7 +3161,7 @@@ static inline int iocb_flags(struct fil
        return res;
  }
  
 -static inline int kiocb_set_rw_flags(struct kiocb *ki, int flags)
 +static inline int kiocb_set_rw_flags(struct kiocb *ki, rwf_t flags)
  {
        if (unlikely(flags & ~RWF_SUPPORTED))
                return -EOPNOTSUPP;
diff --combined mm/filemap.c
index 65b4b6e7f7bde69620b73af705ecca33629a8f79,85dfe3bee324a6c89c1d60b28bab5e7f11662935..1e01cb6e5173d1d184878d7faa3f0da50de95882
@@@ -475,6 -475,29 +475,29 @@@ int filemap_fdatawait_range(struct addr
  }
  EXPORT_SYMBOL(filemap_fdatawait_range);
  
+ /**
+  * file_fdatawait_range - wait for writeback to complete
+  * @file:             file pointing to address space structure to wait for
+  * @start_byte:               offset in bytes where the range starts
+  * @end_byte:         offset in bytes where the range ends (inclusive)
+  *
+  * Walk the list of under-writeback pages of the address space that file
+  * refers to, in the given range and wait for all of them.  Check error
+  * status of the address space vs. the file->f_wb_err cursor and return it.
+  *
+  * Since the error status of the file is advanced by this function,
+  * callers are responsible for checking the return value and handling and/or
+  * reporting the error.
+  */
+ int file_fdatawait_range(struct file *file, loff_t start_byte, loff_t end_byte)
+ {
+       struct address_space *mapping = file->f_mapping;
+       __filemap_fdatawait_range(mapping, start_byte, end_byte);
+       return file_check_and_advance_wb_err(file);
+ }
+ EXPORT_SYMBOL(file_fdatawait_range);
  /**
   * filemap_fdatawait_keep_errors - wait for writeback without clearing errors
   * @mapping: address space structure to wait for
   */
  int filemap_fdatawait_keep_errors(struct address_space *mapping)
  {
-       loff_t i_size = i_size_read(mapping->host);
-       if (i_size == 0)
-               return 0;
-       __filemap_fdatawait_range(mapping, 0, i_size - 1);
+       __filemap_fdatawait_range(mapping, 0, LLONG_MAX);
        return filemap_check_and_keep_errors(mapping);
  }
  EXPORT_SYMBOL(filemap_fdatawait_keep_errors);
  
- /**
-  * filemap_fdatawait - wait for all under-writeback pages to complete
-  * @mapping: address space structure to wait for
-  *
-  * Walk the list of under-writeback pages of the given address space
-  * and wait for all of them.  Check error status of the address space
-  * and return it.
-  *
-  * Since the error status of the address space is cleared by this function,
-  * callers are responsible for checking the return value and handling and/or
-  * reporting the error.
-  */
- int filemap_fdatawait(struct address_space *mapping)
+ static bool mapping_needs_writeback(struct address_space *mapping)
  {
-       loff_t i_size = i_size_read(mapping->host);
-       if (i_size == 0)
-               return 0;
-       return filemap_fdatawait_range(mapping, 0, i_size - 1);
+       return (!dax_mapping(mapping) && mapping->nrpages) ||
+           (dax_mapping(mapping) && mapping->nrexceptional);
  }
- EXPORT_SYMBOL(filemap_fdatawait);
  
  int filemap_write_and_wait(struct address_space *mapping)
  {
        int err = 0;
  
-       if ((!dax_mapping(mapping) && mapping->nrpages) ||
-           (dax_mapping(mapping) && mapping->nrexceptional)) {
+       if (mapping_needs_writeback(mapping)) {
                err = filemap_fdatawrite(mapping);
                /*
                 * Even if the above returned error, the pages may be
@@@ -566,8 -566,7 +566,7 @@@ int filemap_write_and_wait_range(struc
  {
        int err = 0;
  
-       if ((!dax_mapping(mapping) && mapping->nrpages) ||
-           (dax_mapping(mapping) && mapping->nrexceptional)) {
+       if (mapping_needs_writeback(mapping)) {
                err = __filemap_fdatawrite_range(mapping, lstart, lend,
                                                 WB_SYNC_ALL);
                /* See comment of filemap_write_and_wait() */
@@@ -589,7 -588,7 +588,7 @@@ EXPORT_SYMBOL(filemap_write_and_wait_ra
  
  void __filemap_set_wb_err(struct address_space *mapping, int err)
  {
-       errseq_t eseq = __errseq_set(&mapping->wb_err, err);
+       errseq_t eseq = errseq_set(&mapping->wb_err, err);
  
        trace_filemap_set_wb_err(mapping, eseq);
  }
@@@ -656,8 -655,7 +655,7 @@@ int file_write_and_wait_range(struct fi
        int err = 0, err2;
        struct address_space *mapping = file->f_mapping;
  
-       if ((!dax_mapping(mapping) && mapping->nrpages) ||
-           (dax_mapping(mapping) && mapping->nrexceptional)) {
+       if (mapping_needs_writeback(mapping)) {
                err = __filemap_fdatawrite_range(mapping, lstart, lend,
                                                 WB_SYNC_ALL);
                /* See comment of filemap_write_and_wait() */
@@@ -885,7 -883,6 +883,7 @@@ void __init pagecache_init(void
        page_writeback_init();
  }
  
 +/* This has the same layout as wait_bit_key - see fs/cachefiles/rdwr.c */
  struct wait_page_key {
        struct page *page;
        int bit_nr;
@@@ -910,10 -907,8 +908,10 @@@ static int wake_page_function(wait_queu
  
        if (wait_page->bit_nr != key->bit_nr)
                return 0;
 +
 +      /* Stop walking if it's locked */
        if (test_bit(key->bit_nr, &key->page->flags))
 -              return 0;
 +              return -1;
  
        return autoremove_wake_function(wait, mode, sync, key);
  }
@@@ -967,7 -962,6 +965,7 @@@ static inline int wait_on_page_bit_comm
        int ret = 0;
  
        init_wait(wait);
 +      wait->flags = lock ? WQ_FLAG_EXCLUSIVE : 0;
        wait->func = wake_page_function;
        wait_page.page = page;
        wait_page.bit_nr = bit_nr;
                spin_lock_irq(&q->lock);
  
                if (likely(list_empty(&wait->entry))) {
 -                      if (lock)
 -                              __add_wait_queue_entry_tail_exclusive(q, wait);
 -                      else
 -                              __add_wait_queue(q, wait);
 +                      __add_wait_queue_entry_tail(q, wait);
                        SetPageWaiters(page);
                }
  
  
                if (likely(test_bit(bit_nr, &page->flags))) {
                        io_schedule();
 -                      if (unlikely(signal_pending_state(state, current))) {
 -                              ret = -EINTR;
 -                              break;
 -                      }
                }
  
                if (lock) {
                        if (!test_bit(bit_nr, &page->flags))
                                break;
                }
 +
 +              if (unlikely(signal_pending_state(state, current))) {
 +                      ret = -EINTR;
 +                      break;
 +              }
        }
  
        finish_wait(q, wait);
@@@ -1041,7 -1037,7 +1039,7 @@@ void add_page_wait_queue(struct page *p
        unsigned long flags;
  
        spin_lock_irqsave(&q->lock, flags);
 -      __add_wait_queue(q, waiter);
 +      __add_wait_queue_entry_tail(q, waiter);
        SetPageWaiters(page);
        spin_unlock_irqrestore(&q->lock, flags);
  }
This page took 0.116839 seconds and 4 git commands to generate.