Merge branch 'for-3.20/bdi' of git://git.kernel.dk/linux-block
[linux-drm-fsl-dcu.git] / fs / xfs / xfs_file.c
index 5684ac3e7d18311c7880247a08359e6029d1374b..1cdba95c78cb3e2475de29e0b6d88df3604e4cdf 100644 (file)
@@ -127,6 +127,42 @@ xfs_iozero(
        return (-status);
 }
 
+int
+xfs_update_prealloc_flags(
+       struct xfs_inode        *ip,
+       enum xfs_prealloc_flags flags)
+{
+       struct xfs_trans        *tp;
+       int                     error;
+
+       tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_WRITEID);
+       error = xfs_trans_reserve(tp, &M_RES(ip->i_mount)->tr_writeid, 0, 0);
+       if (error) {
+               xfs_trans_cancel(tp, 0);
+               return error;
+       }
+
+       xfs_ilock(ip, XFS_ILOCK_EXCL);
+       xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
+
+       if (!(flags & XFS_PREALLOC_INVISIBLE)) {
+               ip->i_d.di_mode &= ~S_ISUID;
+               if (ip->i_d.di_mode & S_IXGRP)
+                       ip->i_d.di_mode &= ~S_ISGID;
+               xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+       }
+
+       if (flags & XFS_PREALLOC_SET)
+               ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC;
+       if (flags & XFS_PREALLOC_CLEAR)
+               ip->i_d.di_flags &= ~XFS_DIFLAG_PREALLOC;
+
+       xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+       if (flags & XFS_PREALLOC_SYNC)
+               xfs_trans_set_sync(tp);
+       return xfs_trans_commit(tp, 0);
+}
+
 /*
  * Fsync operations on directories are much simpler than on regular files,
  * as there is no file data to flush, and thus also no need for explicit
@@ -784,8 +820,8 @@ xfs_file_fallocate(
 {
        struct inode            *inode = file_inode(file);
        struct xfs_inode        *ip = XFS_I(inode);
-       struct xfs_trans        *tp;
        long                    error;
+       enum xfs_prealloc_flags flags = 0;
        loff_t                  new_size = 0;
 
        if (!S_ISREG(inode->i_mode))
@@ -822,6 +858,8 @@ xfs_file_fallocate(
                if (error)
                        goto out_unlock;
        } else {
+               flags |= XFS_PREALLOC_SET;
+
                if (!(mode & FALLOC_FL_KEEP_SIZE) &&
                    offset + len > i_size_read(inode)) {
                        new_size = offset + len;
@@ -839,28 +877,10 @@ xfs_file_fallocate(
                        goto out_unlock;
        }
 
-       tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_WRITEID);
-       error = xfs_trans_reserve(tp, &M_RES(ip->i_mount)->tr_writeid, 0, 0);
-       if (error) {
-               xfs_trans_cancel(tp, 0);
-               goto out_unlock;
-       }
-
-       xfs_ilock(ip, XFS_ILOCK_EXCL);
-       xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
-       ip->i_d.di_mode &= ~S_ISUID;
-       if (ip->i_d.di_mode & S_IXGRP)
-               ip->i_d.di_mode &= ~S_ISGID;
-
-       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);
-       xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-
        if (file->f_flags & O_DSYNC)
-               xfs_trans_set_sync(tp);
-       error = xfs_trans_commit(tp, 0);
+               flags |= XFS_PREALLOC_SYNC;
+
+       error = xfs_update_prealloc_flags(ip, flags);
        if (error)
                goto out_unlock;
 
@@ -1384,5 +1404,4 @@ static const struct vm_operations_struct xfs_file_vm_ops = {
        .fault          = filemap_fault,
        .map_pages      = filemap_map_pages,
        .page_mkwrite   = xfs_vm_page_mkwrite,
-       .remap_pages    = generic_file_remap_pages,
 };