Commit 8add71ca authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Dave Chinner

xfs: factor out a xfs_update_prealloc_flags() helper

This logic is duplicated in xfs_file_fallocate and xfs_ioc_space, and
we'll need another copy of it for pNFS block support.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent 4d949021
...@@ -127,6 +127,42 @@ xfs_iozero( ...@@ -127,6 +127,42 @@ xfs_iozero(
return (-status); 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, * 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 * as there is no file data to flush, and thus also no need for explicit
...@@ -784,8 +820,8 @@ xfs_file_fallocate( ...@@ -784,8 +820,8 @@ xfs_file_fallocate(
{ {
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
struct xfs_inode *ip = XFS_I(inode); struct xfs_inode *ip = XFS_I(inode);
struct xfs_trans *tp;
long error; long error;
enum xfs_prealloc_flags flags = 0;
loff_t new_size = 0; loff_t new_size = 0;
if (!S_ISREG(inode->i_mode)) if (!S_ISREG(inode->i_mode))
...@@ -822,6 +858,8 @@ xfs_file_fallocate( ...@@ -822,6 +858,8 @@ xfs_file_fallocate(
if (error) if (error)
goto out_unlock; goto out_unlock;
} else { } else {
flags |= XFS_PREALLOC_SET;
if (!(mode & FALLOC_FL_KEEP_SIZE) && if (!(mode & FALLOC_FL_KEEP_SIZE) &&
offset + len > i_size_read(inode)) { offset + len > i_size_read(inode)) {
new_size = offset + len; new_size = offset + len;
...@@ -839,28 +877,10 @@ xfs_file_fallocate( ...@@ -839,28 +877,10 @@ xfs_file_fallocate(
goto out_unlock; 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) if (file->f_flags & O_DSYNC)
xfs_trans_set_sync(tp); flags |= XFS_PREALLOC_SYNC;
error = xfs_trans_commit(tp, 0);
error = xfs_update_prealloc_flags(ip, flags);
if (error) if (error)
goto out_unlock; goto out_unlock;
......
...@@ -377,6 +377,15 @@ int xfs_droplink(struct xfs_trans *, struct xfs_inode *); ...@@ -377,6 +377,15 @@ int xfs_droplink(struct xfs_trans *, struct xfs_inode *);
int xfs_bumplink(struct xfs_trans *, struct xfs_inode *); int xfs_bumplink(struct xfs_trans *, struct xfs_inode *);
/* from xfs_file.c */ /* from xfs_file.c */
enum xfs_prealloc_flags {
XFS_PREALLOC_SET = (1 << 1),
XFS_PREALLOC_CLEAR = (1 << 2),
XFS_PREALLOC_SYNC = (1 << 3),
XFS_PREALLOC_INVISIBLE = (1 << 4),
};
int xfs_update_prealloc_flags(struct xfs_inode *,
enum xfs_prealloc_flags);
int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t); int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t);
int xfs_iozero(struct xfs_inode *, loff_t, size_t); int xfs_iozero(struct xfs_inode *, loff_t, size_t);
......
...@@ -606,11 +606,8 @@ xfs_ioc_space( ...@@ -606,11 +606,8 @@ xfs_ioc_space(
unsigned int cmd, unsigned int cmd,
xfs_flock64_t *bf) xfs_flock64_t *bf)
{ {
struct xfs_mount *mp = ip->i_mount;
struct xfs_trans *tp;
struct iattr iattr; struct iattr iattr;
bool setprealloc = false; enum xfs_prealloc_flags flags = 0;
bool clrprealloc = false;
int error; int error;
/* /*
...@@ -630,6 +627,11 @@ xfs_ioc_space( ...@@ -630,6 +627,11 @@ xfs_ioc_space(
if (!S_ISREG(inode->i_mode)) if (!S_ISREG(inode->i_mode))
return -EINVAL; return -EINVAL;
if (filp->f_flags & O_DSYNC)
flags |= XFS_PREALLOC_SYNC;
if (ioflags & XFS_IO_INVIS)
flags |= XFS_PREALLOC_INVISIBLE;
error = mnt_want_write_file(filp); error = mnt_want_write_file(filp);
if (error) if (error)
return error; return error;
...@@ -673,25 +675,23 @@ xfs_ioc_space( ...@@ -673,25 +675,23 @@ xfs_ioc_space(
} }
if (bf->l_start < 0 || if (bf->l_start < 0 ||
bf->l_start > mp->m_super->s_maxbytes || bf->l_start > inode->i_sb->s_maxbytes ||
bf->l_start + bf->l_len < 0 || bf->l_start + bf->l_len < 0 ||
bf->l_start + bf->l_len >= mp->m_super->s_maxbytes) { bf->l_start + bf->l_len >= inode->i_sb->s_maxbytes) {
error = -EINVAL; error = -EINVAL;
goto out_unlock; goto out_unlock;
} }
switch (cmd) { switch (cmd) {
case XFS_IOC_ZERO_RANGE: case XFS_IOC_ZERO_RANGE:
flags |= XFS_PREALLOC_SET;
error = xfs_zero_file_space(ip, bf->l_start, bf->l_len); error = xfs_zero_file_space(ip, bf->l_start, bf->l_len);
if (!error)
setprealloc = true;
break; break;
case XFS_IOC_RESVSP: case XFS_IOC_RESVSP:
case XFS_IOC_RESVSP64: case XFS_IOC_RESVSP64:
flags |= XFS_PREALLOC_SET;
error = xfs_alloc_file_space(ip, bf->l_start, bf->l_len, error = xfs_alloc_file_space(ip, bf->l_start, bf->l_len,
XFS_BMAPI_PREALLOC); XFS_BMAPI_PREALLOC);
if (!error)
setprealloc = true;
break; break;
case XFS_IOC_UNRESVSP: case XFS_IOC_UNRESVSP:
case XFS_IOC_UNRESVSP64: case XFS_IOC_UNRESVSP64:
...@@ -701,6 +701,7 @@ xfs_ioc_space( ...@@ -701,6 +701,7 @@ xfs_ioc_space(
case XFS_IOC_ALLOCSP64: case XFS_IOC_ALLOCSP64:
case XFS_IOC_FREESP: case XFS_IOC_FREESP:
case XFS_IOC_FREESP64: case XFS_IOC_FREESP64:
flags |= XFS_PREALLOC_CLEAR;
if (bf->l_start > XFS_ISIZE(ip)) { if (bf->l_start > XFS_ISIZE(ip)) {
error = xfs_alloc_file_space(ip, XFS_ISIZE(ip), error = xfs_alloc_file_space(ip, XFS_ISIZE(ip),
bf->l_start - XFS_ISIZE(ip), 0); bf->l_start - XFS_ISIZE(ip), 0);
...@@ -712,8 +713,6 @@ xfs_ioc_space( ...@@ -712,8 +713,6 @@ xfs_ioc_space(
iattr.ia_size = bf->l_start; iattr.ia_size = bf->l_start;
error = xfs_setattr_size(ip, &iattr); error = xfs_setattr_size(ip, &iattr);
if (!error)
clrprealloc = true;
break; break;
default: default:
ASSERT(0); ASSERT(0);
...@@ -723,32 +722,7 @@ xfs_ioc_space( ...@@ -723,32 +722,7 @@ xfs_ioc_space(
if (error) if (error)
goto out_unlock; goto out_unlock;
tp = xfs_trans_alloc(mp, XFS_TRANS_WRITEID); error = xfs_update_prealloc_flags(ip, flags);
error = xfs_trans_reserve(tp, &M_RES(mp)->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);
if (!(ioflags & XFS_IO_INVIS)) {
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 (setprealloc)
ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC;
else if (clrprealloc)
ip->i_d.di_flags &= ~XFS_DIFLAG_PREALLOC;
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
if (filp->f_flags & O_DSYNC)
xfs_trans_set_sync(tp);
error = xfs_trans_commit(tp, 0);
out_unlock: out_unlock:
xfs_iunlock(ip, XFS_IOLOCK_EXCL); xfs_iunlock(ip, XFS_IOLOCK_EXCL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment