xfs: fold xfs_change_file_space into xfs_ioc_space
Now that only one caller of xfs_change_file_space is left it can be merged into said caller. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Ben Myers <bpm@sgi.com>
This commit is contained in:
parent
83aee9e4c2
commit
865e9446b4
|
@ -1385,7 +1385,7 @@ xfs_free_file_space(
|
|||
}
|
||||
|
||||
|
||||
STATIC int
|
||||
int
|
||||
xfs_zero_file_space(
|
||||
struct xfs_inode *ip,
|
||||
xfs_off_t offset,
|
||||
|
@ -1445,182 +1445,6 @@ out:
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
* xfs_change_file_space()
|
||||
* This routine allocates or frees disk space for the given file.
|
||||
* The user specified parameters are checked for alignment and size
|
||||
* limitations.
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success
|
||||
* errno on error
|
||||
*
|
||||
*/
|
||||
int
|
||||
xfs_change_file_space(
|
||||
xfs_inode_t *ip,
|
||||
int cmd,
|
||||
xfs_flock64_t *bf,
|
||||
xfs_off_t offset,
|
||||
int attr_flags)
|
||||
{
|
||||
xfs_mount_t *mp = ip->i_mount;
|
||||
int clrprealloc;
|
||||
int error;
|
||||
xfs_fsize_t fsize;
|
||||
int setprealloc;
|
||||
xfs_off_t startoffset;
|
||||
xfs_trans_t *tp;
|
||||
struct iattr iattr;
|
||||
|
||||
if (!S_ISREG(ip->i_d.di_mode))
|
||||
return XFS_ERROR(EINVAL);
|
||||
|
||||
switch (bf->l_whence) {
|
||||
case 0: /*SEEK_SET*/
|
||||
break;
|
||||
case 1: /*SEEK_CUR*/
|
||||
bf->l_start += offset;
|
||||
break;
|
||||
case 2: /*SEEK_END*/
|
||||
bf->l_start += XFS_ISIZE(ip);
|
||||
break;
|
||||
default:
|
||||
return XFS_ERROR(EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* length of <= 0 for resv/unresv/zero is invalid. length for
|
||||
* alloc/free is ignored completely and we have no idea what userspace
|
||||
* might have set it to, so set it to zero to allow range
|
||||
* checks to pass.
|
||||
*/
|
||||
switch (cmd) {
|
||||
case XFS_IOC_ZERO_RANGE:
|
||||
case XFS_IOC_RESVSP:
|
||||
case XFS_IOC_RESVSP64:
|
||||
case XFS_IOC_UNRESVSP:
|
||||
case XFS_IOC_UNRESVSP64:
|
||||
if (bf->l_len <= 0)
|
||||
return XFS_ERROR(EINVAL);
|
||||
break;
|
||||
default:
|
||||
bf->l_len = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (bf->l_start < 0 ||
|
||||
bf->l_start > mp->m_super->s_maxbytes ||
|
||||
bf->l_start + bf->l_len < 0 ||
|
||||
bf->l_start + bf->l_len >= mp->m_super->s_maxbytes)
|
||||
return XFS_ERROR(EINVAL);
|
||||
|
||||
bf->l_whence = 0;
|
||||
|
||||
startoffset = bf->l_start;
|
||||
fsize = XFS_ISIZE(ip);
|
||||
|
||||
setprealloc = clrprealloc = 0;
|
||||
switch (cmd) {
|
||||
case XFS_IOC_ZERO_RANGE:
|
||||
error = xfs_zero_file_space(ip, startoffset, bf->l_len);
|
||||
if (error)
|
||||
return error;
|
||||
setprealloc = 1;
|
||||
break;
|
||||
|
||||
case XFS_IOC_RESVSP:
|
||||
case XFS_IOC_RESVSP64:
|
||||
error = xfs_alloc_file_space(ip, startoffset, bf->l_len,
|
||||
XFS_BMAPI_PREALLOC);
|
||||
if (error)
|
||||
return error;
|
||||
setprealloc = 1;
|
||||
break;
|
||||
|
||||
case XFS_IOC_UNRESVSP:
|
||||
case XFS_IOC_UNRESVSP64:
|
||||
error = xfs_free_file_space(ip, startoffset, bf->l_len);
|
||||
if (error)
|
||||
return error;
|
||||
break;
|
||||
|
||||
case XFS_IOC_ALLOCSP:
|
||||
case XFS_IOC_ALLOCSP64:
|
||||
case XFS_IOC_FREESP:
|
||||
case XFS_IOC_FREESP64:
|
||||
/*
|
||||
* These operations actually do IO when extending the file, but
|
||||
* the allocation is done seperately to the zeroing that is
|
||||
* done. This set of operations need to be serialised against
|
||||
* other IO operations, such as truncate and buffered IO. We
|
||||
* need to take the IOLOCK here to serialise the allocation and
|
||||
* zeroing IO to prevent other IOLOCK holders (e.g. getbmap,
|
||||
* truncate, direct IO) from racing against the transient
|
||||
* allocated but not written state we can have here.
|
||||
*/
|
||||
if (startoffset > fsize) {
|
||||
error = xfs_alloc_file_space(ip, fsize,
|
||||
startoffset - fsize, 0);
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
|
||||
iattr.ia_valid = ATTR_SIZE;
|
||||
iattr.ia_size = startoffset;
|
||||
|
||||
error = xfs_setattr_size(ip, &iattr);
|
||||
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
clrprealloc = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
ASSERT(0);
|
||||
return XFS_ERROR(EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* update the inode timestamp, mode, and prealloc flag bits
|
||||
*/
|
||||
tp = xfs_trans_alloc(mp, XFS_TRANS_WRITEID);
|
||||
error = xfs_trans_reserve(tp, &M_RES(mp)->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 ((attr_flags & XFS_ATTR_DMI) == 0) {
|
||||
ip->i_d.di_mode &= ~S_ISUID;
|
||||
|
||||
/*
|
||||
* Note that we don't have to worry about mandatory
|
||||
* file locking being disabled here because we only
|
||||
* clear the S_ISGID bit if the Group execute bit is
|
||||
* on, but if it was on then mandatory locking wouldn't
|
||||
* have been enabled.
|
||||
*/
|
||||
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 (attr_flags & XFS_ATTR_SYNC)
|
||||
xfs_trans_set_sync(tp);
|
||||
return xfs_trans_commit(tp, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to check that the format of the data fork in the temporary inode is
|
||||
* valid for the target inode before doing the swap. This is not a problem with
|
||||
|
|
|
@ -93,13 +93,12 @@ int xfs_bmap_last_extent(struct xfs_trans *tp, struct xfs_inode *ip,
|
|||
int *is_empty);
|
||||
|
||||
/* preallocation and hole punch interface */
|
||||
int xfs_change_file_space(struct xfs_inode *ip, int cmd,
|
||||
xfs_flock64_t *bf, xfs_off_t offset,
|
||||
int attr_flags);
|
||||
int xfs_alloc_file_space(struct xfs_inode *ip, xfs_off_t offset,
|
||||
xfs_off_t len, int alloc_type);
|
||||
int xfs_free_file_space(struct xfs_inode *ip, xfs_off_t offset,
|
||||
xfs_off_t len);
|
||||
int xfs_zero_file_space(struct xfs_inode *ip, xfs_off_t offset,
|
||||
xfs_off_t len);
|
||||
|
||||
/* EOF block manipulation functions */
|
||||
bool xfs_can_free_eofblocks(struct xfs_inode *ip, bool force);
|
||||
|
|
|
@ -641,7 +641,11 @@ xfs_ioc_space(
|
|||
unsigned int cmd,
|
||||
xfs_flock64_t *bf)
|
||||
{
|
||||
int attr_flags = 0;
|
||||
struct xfs_mount *mp = ip->i_mount;
|
||||
struct xfs_trans *tp;
|
||||
struct iattr iattr;
|
||||
bool setprealloc = false;
|
||||
bool clrprealloc = false;
|
||||
int error;
|
||||
|
||||
/*
|
||||
|
@ -661,17 +665,127 @@ xfs_ioc_space(
|
|||
if (!S_ISREG(inode->i_mode))
|
||||
return -XFS_ERROR(EINVAL);
|
||||
|
||||
if (filp->f_flags & O_DSYNC)
|
||||
attr_flags |= XFS_ATTR_SYNC;
|
||||
|
||||
if (ioflags & IO_INVIS)
|
||||
attr_flags |= XFS_ATTR_DMI;
|
||||
|
||||
error = mnt_want_write_file(filp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
xfs_ilock(ip, XFS_IOLOCK_EXCL);
|
||||
error = xfs_change_file_space(ip, cmd, bf, filp->f_pos, attr_flags);
|
||||
|
||||
switch (bf->l_whence) {
|
||||
case 0: /*SEEK_SET*/
|
||||
break;
|
||||
case 1: /*SEEK_CUR*/
|
||||
bf->l_start += filp->f_pos;
|
||||
break;
|
||||
case 2: /*SEEK_END*/
|
||||
bf->l_start += XFS_ISIZE(ip);
|
||||
break;
|
||||
default:
|
||||
error = XFS_ERROR(EINVAL);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* length of <= 0 for resv/unresv/zero is invalid. length for
|
||||
* alloc/free is ignored completely and we have no idea what userspace
|
||||
* might have set it to, so set it to zero to allow range
|
||||
* checks to pass.
|
||||
*/
|
||||
switch (cmd) {
|
||||
case XFS_IOC_ZERO_RANGE:
|
||||
case XFS_IOC_RESVSP:
|
||||
case XFS_IOC_RESVSP64:
|
||||
case XFS_IOC_UNRESVSP:
|
||||
case XFS_IOC_UNRESVSP64:
|
||||
if (bf->l_len <= 0) {
|
||||
error = XFS_ERROR(EINVAL);
|
||||
goto out_unlock;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
bf->l_len = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (bf->l_start < 0 ||
|
||||
bf->l_start > mp->m_super->s_maxbytes ||
|
||||
bf->l_start + bf->l_len < 0 ||
|
||||
bf->l_start + bf->l_len >= mp->m_super->s_maxbytes) {
|
||||
error = XFS_ERROR(EINVAL);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case XFS_IOC_ZERO_RANGE:
|
||||
error = xfs_zero_file_space(ip, bf->l_start, bf->l_len);
|
||||
if (!error)
|
||||
setprealloc = true;
|
||||
break;
|
||||
case XFS_IOC_RESVSP:
|
||||
case XFS_IOC_RESVSP64:
|
||||
error = xfs_alloc_file_space(ip, bf->l_start, bf->l_len,
|
||||
XFS_BMAPI_PREALLOC);
|
||||
if (!error)
|
||||
setprealloc = true;
|
||||
break;
|
||||
case XFS_IOC_UNRESVSP:
|
||||
case XFS_IOC_UNRESVSP64:
|
||||
error = xfs_free_file_space(ip, bf->l_start, bf->l_len);
|
||||
break;
|
||||
case XFS_IOC_ALLOCSP:
|
||||
case XFS_IOC_ALLOCSP64:
|
||||
case XFS_IOC_FREESP:
|
||||
case XFS_IOC_FREESP64:
|
||||
if (bf->l_start > XFS_ISIZE(ip)) {
|
||||
error = xfs_alloc_file_space(ip, XFS_ISIZE(ip),
|
||||
bf->l_start - XFS_ISIZE(ip), 0);
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
iattr.ia_valid = ATTR_SIZE;
|
||||
iattr.ia_size = bf->l_start;
|
||||
|
||||
error = xfs_setattr_size(ip, &iattr);
|
||||
if (!error)
|
||||
clrprealloc = true;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
error = XFS_ERROR(EINVAL);
|
||||
}
|
||||
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
|
||||
tp = xfs_trans_alloc(mp, XFS_TRANS_WRITEID);
|
||||
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 & 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:
|
||||
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
|
||||
mnt_drop_write_file(filp);
|
||||
return -error;
|
||||
|
|
|
@ -30,9 +30,7 @@ extern void xfs_setup_inode(struct xfs_inode *);
|
|||
/*
|
||||
* Internal setattr interfaces.
|
||||
*/
|
||||
#define XFS_ATTR_DMI 0x01 /* invocation from a DMI function */
|
||||
#define XFS_ATTR_NOACL 0x08 /* Don't call xfs_acl_chmod */
|
||||
#define XFS_ATTR_SYNC 0x10 /* synchronous operation required */
|
||||
#define XFS_ATTR_NOACL 0x01 /* Don't call xfs_acl_chmod */
|
||||
|
||||
extern int xfs_setattr_nonsize(struct xfs_inode *ip, struct iattr *vap,
|
||||
int flags);
|
||||
|
|
Loading…
Reference in New Issue