Merge tag 'xfs-for-linus-3.15-rc1' of git://oss.sgi.com/xfs/xfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 4 Apr 2014 22:50:08 +0000 (15:50 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 4 Apr 2014 22:50:08 +0000 (15:50 -0700)
Pull xfs update from Dave Chinner:
 "There are a couple of new fallocate features in this request - it was
  decided that it was easiest to push them through the XFS tree using
  topic branches and have the ext4 support be based on those branches.
  Hence you may see some overlap with the ext4 tree merge depending on
  how they including those topic branches into their tree.  Other than
  that, there is O_TMPFILE support, some cleanups and bug fixes.

  The main changes in the XFS tree for 3.15-rc1 are:

   - O_TMPFILE support
   - allowing AIO+DIO writes beyond EOF
   - FALLOC_FL_COLLAPSE_RANGE support for fallocate syscall and XFS
     implementation
   - FALLOC_FL_ZERO_RANGE support for fallocate syscall and XFS
     implementation
   - IO verifier cleanup and rework
   - stack usage reduction changes
   - vm_map_ram NOIO context fixes to remove lockdep warings
   - various bug fixes and cleanups"

* tag 'xfs-for-linus-3.15-rc1' of git://oss.sgi.com/xfs/xfs: (34 commits)
  xfs: fix directory hash ordering bug
  xfs: extra semi-colon breaks a condition
  xfs: Add support for FALLOC_FL_ZERO_RANGE
  fs: Introduce FALLOC_FL_ZERO_RANGE flag for fallocate
  xfs: inode log reservations are still too small
  xfs: xfs_check_page_type buffer checks need help
  xfs: avoid AGI/AGF deadlock scenario for inode chunk allocation
  xfs: use NOIO contexts for vm_map_ram
  xfs: don't leak EFSBADCRC to userspace
  xfs: fix directory inode iolock lockdep false positive
  xfs: allocate xfs_da_args to reduce stack footprint
  xfs: always do log forces via the workqueue
  xfs: modify verifiers to differentiate CRC from other errors
  xfs: print useful caller information in xfs_error_report
  xfs: add xfs_verifier_error()
  xfs: add helper for updating checksums on xfs_bufs
  xfs: add helper for verifying checksums on xfs_bufs
  xfs: Use defines for CRC offsets in all cases
  xfs: skip pointless CRC updates after verifier failures
  xfs: Add support FALLOC_FL_COLLAPSE_RANGE for fallocate
  ...

1  2 
fs/direct-io.c
fs/open.c
fs/xfs/xfs_file.c
include/linux/fs.h

diff --combined fs/direct-io.c
index 6e6bff3752446036990fb4a5d0eca4cdaad3fac5,a701752dd7505a139b1a52282ba788d7b1271857..31ba0935e32ed2f271253a1d828778a91193b211
@@@ -664,6 -664,7 +664,6 @@@ static inline int dio_new_bio(struct di
                goto out;
        sector = start_sector << (sdio->blkbits - 9);
        nr_pages = min(sdio->pages_in_io, bio_get_nr_vecs(map_bh->b_bdev));
 -      nr_pages = min(nr_pages, BIO_MAX_PAGES);
        BUG_ON(nr_pages <= 0);
        dio_bio_alloc(dio, sdio, map_bh->b_bdev, sector, nr_pages);
        sdio->boundary = 0;
@@@ -1193,13 -1194,19 +1193,19 @@@ do_blockdev_direct_IO(int rw, struct ki
        }
  
        /*
-        * For file extending writes updating i_size before data
-        * writeouts complete can expose uninitialized blocks. So
-        * even for AIO, we need to wait for i/o to complete before
-        * returning in this case.
+        * For file extending writes updating i_size before data writeouts
+        * complete can expose uninitialized blocks in dumb filesystems.
+        * In that case we need to wait for I/O completion even if asked
+        * for an asynchronous write.
         */
-       dio->is_async = !is_sync_kiocb(iocb) && !((rw & WRITE) &&
-               (end > i_size_read(inode)));
+       if (is_sync_kiocb(iocb))
+               dio->is_async = false;
+       else if (!(dio->flags & DIO_ASYNC_EXTEND) &&
+             (rw & WRITE) && end > i_size_read(inode))
+               dio->is_async = false;
+       else
+               dio->is_async = true;
        dio->inode = inode;
        dio->rw = rw;
  
diff --combined fs/open.c
index b9ed8b25c108c69d68889b5b6eadac9878eb7bd9,c4465b2f84410d1b7601b80fd36229a3cd943525..631aea815def32946433b8aebed9a312d0fc872c
+++ b/fs/open.c
@@@ -231,7 -231,13 +231,13 @@@ int do_fallocate(struct file *file, in
                return -EINVAL;
  
        /* Return error if mode is not supported */
-       if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
+       if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
+                    FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE))
+               return -EOPNOTSUPP;
+       /* Punch hole and zero range are mutually exclusive */
+       if ((mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE)) ==
+           (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE))
                return -EOPNOTSUPP;
  
        /* Punch hole must have keep size set */
            !(mode & FALLOC_FL_KEEP_SIZE))
                return -EOPNOTSUPP;
  
+       /* Collapse range should only be used exclusively. */
+       if ((mode & FALLOC_FL_COLLAPSE_RANGE) &&
+           (mode & ~FALLOC_FL_COLLAPSE_RANGE))
+               return -EINVAL;
        if (!(file->f_mode & FMODE_WRITE))
                return -EBADF;
  
-       /* It's not possible punch hole on append only file */
-       if (mode & FALLOC_FL_PUNCH_HOLE && IS_APPEND(inode))
+       /*
+        * It's not possible to punch hole or perform collapse range
+        * on append only file
+        */
+       if (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE)
+           && IS_APPEND(inode))
                return -EPERM;
  
        if (IS_IMMUTABLE(inode))
        if (((offset + len) > inode->i_sb->s_maxbytes) || ((offset + len) < 0))
                return -EFBIG;
  
+       /*
+        * There is no need to overlap collapse range with EOF, in which case
+        * it is effectively a truncate operation
+        */
+       if ((mode & FALLOC_FL_COLLAPSE_RANGE) &&
+           (offset + len >= i_size_read(inode)))
+               return -EINVAL;
        if (!file->f_op->fallocate)
                return -EOPNOTSUPP;
  
@@@ -705,10 -728,6 +728,10 @@@ static int do_dentry_open(struct file *
                return 0;
        }
  
 +      /* POSIX.1-2008/SUSv4 Section XSI 2.9.7 */
 +      if (S_ISREG(inode->i_mode))
 +              f->f_mode |= FMODE_ATOMIC_POS;
 +
        f->f_op = fops_get(inode->i_fop);
        if (unlikely(WARN_ON(!f->f_op))) {
                error = -ENODEV;
diff --combined fs/xfs/xfs_file.c
index 64b48eade91d14c79408b6863f199e9181350f81,8fb97a65286ed2af463f63e7bdb07fe0cfa7a52e..f7abff8c16ca7361d3e32f1842ae1daed15e651e
@@@ -799,7 -799,7 +799,7 @@@ xfs_file_aio_write
                XFS_STATS_ADD(xs_write_bytes, ret);
  
                /* Handle various SYNC-type writes */
 -              err = generic_write_sync(file, pos, ret);
 +              err = generic_write_sync(file, iocb->ki_pos - ret, ret);
                if (err < 0)
                        ret = err;
        }
@@@ -823,7 -823,8 +823,8 @@@ xfs_file_fallocate
  
        if (!S_ISREG(inode->i_mode))
                return -EINVAL;
-       if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
+       if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
+                    FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE))
                return -EOPNOTSUPP;
  
        xfs_ilock(ip, XFS_IOLOCK_EXCL);
                error = xfs_free_file_space(ip, offset, len);
                if (error)
                        goto out_unlock;
+       } else if (mode & FALLOC_FL_COLLAPSE_RANGE) {
+               unsigned blksize_mask = (1 << inode->i_blkbits) - 1;
+               if (offset & blksize_mask || len & blksize_mask) {
+                       error = -EINVAL;
+                       goto out_unlock;
+               }
+               ASSERT(offset + len < i_size_read(inode));
+               new_size = i_size_read(inode) - len;
+               error = xfs_collapse_file_space(ip, offset, len);
+               if (error)
+                       goto out_unlock;
        } else {
                if (!(mode & FALLOC_FL_KEEP_SIZE) &&
                    offset + len > i_size_read(inode)) {
                                goto out_unlock;
                }
  
-               error = xfs_alloc_file_space(ip, offset, len,
-                                            XFS_BMAPI_PREALLOC);
+               if (mode & FALLOC_FL_ZERO_RANGE)
+                       error = xfs_zero_file_space(ip, offset, len);
+               else
+                       error = xfs_alloc_file_space(ip, offset, len,
+                                                    XFS_BMAPI_PREALLOC);
                if (error)
                        goto out_unlock;
        }
        if (ip->i_d.di_mode & S_IXGRP)
                ip->i_d.di_mode &= ~S_ISGID;
  
-       if (!(mode & FALLOC_FL_PUNCH_HOLE))
+       if (!(mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE)))
                ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC;
  
        xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
diff --combined include/linux/fs.h
index ea80f1cdff064b7c3bf330d186b9954a06985f9b,f7faefcf4843576aa535ac44241b79cca56b7164..81048f9bc7837e3ce32fb12dddf158a09fbaf302
@@@ -123,9 -123,6 +123,9 @@@ typedef void (dio_iodone_t)(struct kioc
  /* File is opened with O_PATH; almost nothing can be done with it */
  #define FMODE_PATH            ((__force fmode_t)0x4000)
  
 +/* File needs atomic accesses to f_pos */
 +#define FMODE_ATOMIC_POS      ((__force fmode_t)0x8000)
 +
  /* File was opened by fanotify and shouldn't generate fanotify events */
  #define FMODE_NONOTIFY                ((__force fmode_t)0x1000000)
  
@@@ -419,7 -416,6 +419,7 @@@ struct address_space 
        struct mutex            i_mmap_mutex;   /* protect tree, count, list */
        /* Protected by tree_lock together with the radix tree */
        unsigned long           nrpages;        /* number of total pages */
 +      unsigned long           nrshadows;      /* number of shadow entries */
        pgoff_t                 writeback_index;/* writeback starts here */
        const struct address_space_operations *a_ops;   /* methods */
        unsigned long           flags;          /* error bits/gfp mask */
@@@ -590,9 -586,6 +590,9 @@@ struct inode 
        atomic_t                i_count;
        atomic_t                i_dio_count;
        atomic_t                i_writecount;
 +#ifdef CONFIG_IMA
 +      atomic_t                i_readcount; /* struct files open RO */
 +#endif
        const struct file_operations    *i_fop; /* former ->i_op->default_file_ops */
        struct file_lock        *i_flock;
        struct address_space    i_data;
        struct hlist_head       i_fsnotify_marks;
  #endif
  
 -#ifdef CONFIG_IMA
 -      atomic_t                i_readcount; /* struct files open RO */
 -#endif
        void                    *i_private; /* fs or device private pointer */
  };
  
@@@ -784,14 -780,13 +784,14 @@@ struct file 
        const struct file_operations    *f_op;
  
        /*
 -       * Protects f_ep_links, f_flags, f_pos vs i_size in lseek SEEK_CUR.
 +       * Protects f_ep_links, f_flags.
         * Must not be taken from IRQ context.
         */
        spinlock_t              f_lock;
        atomic_long_t           f_count;
        unsigned int            f_flags;
        fmode_t                 f_mode;
 +      struct mutex            f_pos_lock;
        loff_t                  f_pos;
        struct fown_struct      f_owner;
        const struct cred       *f_cred;
  #ifdef CONFIG_DEBUG_WRITECOUNT
        unsigned long f_mnt_write_state;
  #endif
 -};
 +} __attribute__((aligned(4)));        /* lest something weird decides that 2 is OK */
  
  struct file_handle {
        __u32 handle_bytes;
@@@ -893,7 -888,6 +893,7 @@@ static inline int file_check_writeable(
  #define FL_SLEEP      128     /* A blocking lock */
  #define FL_DOWNGRADE_PENDING  256 /* Lease is being downgraded */
  #define FL_UNLOCK_PENDING     512 /* Lease is being broken */
 +#define FL_FILE_PVT   1024    /* lock is private to the file */
  
  /*
   * Special return value from posix_lock_file() and vfs_lock_file() for
@@@ -998,12 -992,12 +998,12 @@@ struct file_lock 
  extern void send_sigio(struct fown_struct *fown, int fd, int band);
  
  #ifdef CONFIG_FILE_LOCKING
 -extern int fcntl_getlk(struct file *, struct flock __user *);
 +extern int fcntl_getlk(struct file *, unsigned int, struct flock __user *);
  extern int fcntl_setlk(unsigned int, struct file *, unsigned int,
                        struct flock __user *);
  
  #if BITS_PER_LONG == 32
 -extern int fcntl_getlk64(struct file *, struct flock64 __user *);
 +extern int fcntl_getlk64(struct file *, unsigned int, struct flock64 __user *);
  extern int fcntl_setlk64(unsigned int, struct file *, unsigned int,
                        struct flock64 __user *);
  #endif
@@@ -1018,7 -1012,7 +1018,7 @@@ extern struct file_lock * locks_alloc_l
  extern void locks_copy_lock(struct file_lock *, struct file_lock *);
  extern void __locks_copy_lock(struct file_lock *, const struct file_lock *);
  extern void locks_remove_posix(struct file *, fl_owner_t);
 -extern void locks_remove_flock(struct file *);
 +extern void locks_remove_file(struct file *);
  extern void locks_release_private(struct file_lock *);
  extern void posix_test_lock(struct file *, struct file_lock *);
  extern int posix_lock_file(struct file *, struct file_lock *, struct file_lock *);
@@@ -1036,8 -1030,7 +1036,8 @@@ extern int lease_modify(struct file_loc
  extern int lock_may_read(struct inode *, loff_t start, unsigned long count);
  extern int lock_may_write(struct inode *, loff_t start, unsigned long count);
  #else /* !CONFIG_FILE_LOCKING */
 -static inline int fcntl_getlk(struct file *file, struct flock __user *user)
 +static inline int fcntl_getlk(struct file *file, unsigned int cmd,
 +                            struct flock __user *user)
  {
        return -EINVAL;
  }
@@@ -1049,8 -1042,7 +1049,8 @@@ static inline int fcntl_setlk(unsigned 
  }
  
  #if BITS_PER_LONG == 32
 -static inline int fcntl_getlk64(struct file *file, struct flock64 __user *user)
 +static inline int fcntl_getlk64(struct file *file, unsigned int cmd,
 +                              struct flock64 __user *user)
  {
        return -EINVAL;
  }
@@@ -1091,7 -1083,7 +1091,7 @@@ static inline void locks_remove_posix(s
        return;
  }
  
 -static inline void locks_remove_flock(struct file *filp)
 +static inline void locks_remove_file(struct file *filp)
  {
        return;
  }
@@@ -1464,7 -1456,7 +1464,7 @@@ extern int vfs_symlink(struct inode *, 
  extern int vfs_link(struct dentry *, struct inode *, struct dentry *, struct inode **);
  extern int vfs_rmdir(struct inode *, struct dentry *);
  extern int vfs_unlink(struct inode *, struct dentry *, struct inode **);
 -extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct inode **);
 +extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct inode **, unsigned int);
  
  /*
   * VFS dentry helper functions.
@@@ -1575,8 -1567,6 +1575,8 @@@ struct inode_operations 
        int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t);
        int (*rename) (struct inode *, struct dentry *,
                        struct inode *, struct dentry *);
 +      int (*rename2) (struct inode *, struct dentry *,
 +                      struct inode *, struct dentry *, unsigned int);
        int (*setattr) (struct dentry *, struct iattr *);
        int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
        int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
@@@ -1919,11 -1909,6 +1919,11 @@@ extern int current_umask(void)
  extern void ihold(struct inode * inode);
  extern void iput(struct inode *);
  
 +static inline struct inode *file_inode(struct file *f)
 +{
 +      return f->f_inode;
 +}
 +
  /* /sys/fs */
  extern struct kobject *fs_kobj;
  
  #define FLOCK_VERIFY_WRITE 2
  
  #ifdef CONFIG_FILE_LOCKING
 -extern int locks_mandatory_locked(struct inode *);
 +extern int locks_mandatory_locked(struct file *);
  extern int locks_mandatory_area(int, struct inode *, struct file *, loff_t, size_t);
  
  /*
@@@ -1956,10 -1941,10 +1956,10 @@@ static inline int mandatory_lock(struc
        return IS_MANDLOCK(ino) && __mandatory_lock(ino);
  }
  
 -static inline int locks_verify_locked(struct inode *inode)
 +static inline int locks_verify_locked(struct file *file)
  {
 -      if (mandatory_lock(inode))
 -              return locks_mandatory_locked(inode);
 +      if (mandatory_lock(file_inode(file)))
 +              return locks_mandatory_locked(file);
        return 0;
  }
  
@@@ -1979,12 -1964,6 +1979,12 @@@ static inline int locks_verify_truncate
  
  static inline int break_lease(struct inode *inode, unsigned int mode)
  {
 +      /*
 +       * Since this check is lockless, we must ensure that any refcounts
 +       * taken are done before checking inode->i_flock. Otherwise, we could
 +       * end up racing with tasks trying to set a new lease on this file.
 +       */
 +      smp_mb();
        if (inode->i_flock)
                return __break_lease(inode, mode, FL_LEASE);
        return 0;
@@@ -2020,7 -1999,7 +2020,7 @@@ static inline int break_deleg_wait(stru
  }
  
  #else /* !CONFIG_FILE_LOCKING */
 -static inline int locks_mandatory_locked(struct inode *inode)
 +static inline int locks_mandatory_locked(struct file *file)
  {
        return 0;
  }
@@@ -2042,7 -2021,7 +2042,7 @@@ static inline int mandatory_lock(struc
        return 0;
  }
  
 -static inline int locks_verify_locked(struct inode *inode)
 +static inline int locks_verify_locked(struct file *file)
  {
        return 0;
  }
@@@ -2100,7 -2079,6 +2100,7 @@@ extern struct file * dentry_open(const 
  extern int filp_close(struct file *, fl_owner_t id);
  
  extern struct filename *getname(const char __user *);
 +extern struct filename *getname_kernel(const char *);
  
  enum {
        FILE_CREATED = 1,
@@@ -2295,13 -2273,7 +2295,13 @@@ extern int filemap_fdatawrite_range(str
  extern int vfs_fsync_range(struct file *file, loff_t start, loff_t end,
                           int datasync);
  extern int vfs_fsync(struct file *file, int datasync);
 -extern int generic_write_sync(struct file *file, loff_t pos, loff_t count);
 +static inline int generic_write_sync(struct file *file, loff_t pos, loff_t count)
 +{
 +      if (!(file->f_flags & O_DSYNC) && !IS_SYNC(file->f_mapping->host))
 +              return 0;
 +      return vfs_fsync_range(file, pos, pos + count - 1,
 +                             (file->f_flags & __O_SYNC) ? 0 : 1);
 +}
  extern void emergency_sync(void);
  extern void emergency_remount(void);
  #ifdef CONFIG_BLOCK
@@@ -2316,6 -2288,11 +2316,6 @@@ static inline bool execute_ok(struct in
        return (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode);
  }
  
 -static inline struct inode *file_inode(struct file *f)
 -{
 -      return f->f_inode;
 -}
 -
  static inline void file_start_write(struct file *file)
  {
        if (!S_ISREG(file_inode(file)->i_mode))
@@@ -2550,6 -2527,9 +2550,9 @@@ enum 
  
        /* filesystem does not support filling holes */
        DIO_SKIP_HOLES  = 0x02,
+       /* filesystem can handle aio writes beyond i_size */
+       DIO_ASYNC_EXTEND = 0x04,
  };
  
  void dio_end_io(struct bio *bio, int error);
@@@ -2572,9 -2552,6 +2575,9 @@@ static inline ssize_t blockdev_direct_I
  void inode_dio_wait(struct inode *inode);
  void inode_dio_done(struct inode *inode);
  
 +extern void inode_set_flags(struct inode *inode, unsigned int flags,
 +                          unsigned int mask);
 +
  extern const struct file_operations generic_ro_fops;
  
  #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))