]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
xfs: preallocation transactions do not need to be synchronous
authorDave Chinner <dchinner@redhat.com>
Fri, 25 Mar 2011 22:13:08 +0000 (09:13 +1100)
committerDave Chinner <david@fromorbit.com>
Fri, 25 Mar 2011 22:13:08 +0000 (09:13 +1100)
Preallocation and hole punch transactions are currently synchronous
and this is causing performance problems in some cases. The
transactions don't need to be synchronous as we don't need to
guarantee the preallocation is persistent on disk until a
fdatasync, fsync, sync operation occurs. If the file is opened
O_SYNC or O_DATASYNC, only then should the transaction be issued
synchronously.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Alex Elder <aelder@sgi.com>
fs/xfs/linux-2.6/xfs_file.c
fs/xfs/linux-2.6/xfs_ioctl.c
fs/xfs/xfs_vnodeops.c
fs/xfs/xfs_vnodeops.h

index a55c1b46b219b4a1ea4956008d25e5d5990289c5..52aadfbed13229b2f28202088958b12fe1a24fe5 100644 (file)
@@ -896,6 +896,7 @@ xfs_file_fallocate(
        xfs_flock64_t   bf;
        xfs_inode_t     *ip = XFS_I(inode);
        int             cmd = XFS_IOC_RESVSP;
+       int             attr_flags = XFS_ATTR_NOLOCK;
 
        if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
                return -EOPNOTSUPP;
@@ -918,7 +919,10 @@ xfs_file_fallocate(
                        goto out_unlock;
        }
 
-       error = -xfs_change_file_space(ip, cmd, &bf, 0, XFS_ATTR_NOLOCK);
+       if (file->f_flags & O_DSYNC)
+               attr_flags |= XFS_ATTR_SYNC;
+
+       error = -xfs_change_file_space(ip, cmd, &bf, 0, attr_flags);
        if (error)
                goto out_unlock;
 
index 0ca0e3c024d7bac3993707dd7309b3fda9664a07..acca2c5ca3fa82618ef891e26998334640a88869 100644 (file)
@@ -624,6 +624,10 @@ xfs_ioc_space(
 
        if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
                attr_flags |= XFS_ATTR_NONBLOCK;
+
+       if (filp->f_flags & O_DSYNC)
+               attr_flags |= XFS_ATTR_SYNC;
+
        if (ioflags & IO_INVIS)
                attr_flags |= XFS_ATTR_DMI;
 
index 37d8146ee15b2022edecce33ffc896ed84c55e59..c48b4217ec47f652b3769ce912969a46a2924101 100644 (file)
@@ -2831,7 +2831,8 @@ xfs_change_file_space(
                ip->i_d.di_flags &= ~XFS_DIFLAG_PREALLOC;
 
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-       xfs_trans_set_sync(tp);
+       if (attr_flags & XFS_ATTR_SYNC)
+               xfs_trans_set_sync(tp);
 
        error = xfs_trans_commit(tp, 0);
 
index f6702927eee4735846fb678ae3057e4119dc0224..3bcd23353d6cec71d9306a61a469695ccd78e7ca 100644 (file)
@@ -18,6 +18,7 @@ int xfs_setattr(struct xfs_inode *ip, struct iattr *vap, int flags);
 #define        XFS_ATTR_NONBLOCK       0x02    /* return EAGAIN if operation would block */
 #define XFS_ATTR_NOLOCK                0x04    /* Don't grab any conflicting locks */
 #define XFS_ATTR_NOACL         0x08    /* Don't call xfs_acl_chmod */
+#define XFS_ATTR_SYNC          0x10    /* synchronous operation required */
 
 int xfs_readlink(struct xfs_inode *ip, char *link);
 int xfs_release(struct xfs_inode *ip);