Commit 83aee9e4 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Ben Myers

xfs: simplify the fallocate path

Call xfs_alloc_file_space or xfs_free_file_space directly from
xfs_file_fallocate instead of going through xfs_change_file_space.

This simplified the code by removing the unessecary marshalling of the
arguments into an xfs_flock64_t structure and allows removing checks that
are already done in the VFS code.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
Signed-off-by: default avatarBen Myers <bpm@sgi.com>
parent 5f8aca8b
...@@ -965,28 +965,9 @@ xfs_free_eofblocks( ...@@ -965,28 +965,9 @@ xfs_free_eofblocks(
return error; return error;
} }
/* int
* xfs_alloc_file_space()
* This routine allocates disk space for the given file.
*
* If alloc_type == 0, this request is for an ALLOCSP type
* request which will change the file size. In this case, no
* DMAPI event will be generated by the call. A TRUNCATE event
* will be generated later by xfs_setattr.
*
* If alloc_type != 0, this request is for a RESVSP type
* request, and a DMAPI DM_EVENT_WRITE will be generated if the
* lower block boundary byte address is less than the file's
* length.
*
* RETURNS:
* 0 on success
* errno on error
*
*/
STATIC int
xfs_alloc_file_space( xfs_alloc_file_space(
xfs_inode_t *ip, struct xfs_inode *ip,
xfs_off_t offset, xfs_off_t offset,
xfs_off_t len, xfs_off_t len,
int alloc_type) int alloc_type)
...@@ -1231,21 +1212,9 @@ xfs_zero_remaining_bytes( ...@@ -1231,21 +1212,9 @@ xfs_zero_remaining_bytes(
return error; return error;
} }
/* int
* xfs_free_file_space()
* This routine frees disk space for the given file.
*
* This routine is only called by xfs_change_file_space
* for an UNRESVSP type call.
*
* RETURNS:
* 0 on success
* errno on error
*
*/
STATIC int
xfs_free_file_space( xfs_free_file_space(
xfs_inode_t *ip, struct xfs_inode *ip,
xfs_off_t offset, xfs_off_t offset,
xfs_off_t len) xfs_off_t len)
{ {
......
...@@ -96,6 +96,10 @@ int xfs_bmap_last_extent(struct xfs_trans *tp, struct xfs_inode *ip, ...@@ -96,6 +96,10 @@ int xfs_bmap_last_extent(struct xfs_trans *tp, struct xfs_inode *ip,
int xfs_change_file_space(struct xfs_inode *ip, int cmd, int xfs_change_file_space(struct xfs_inode *ip, int cmd,
xfs_flock64_t *bf, xfs_off_t offset, xfs_flock64_t *bf, xfs_off_t offset,
int attr_flags); 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);
/* EOF block manipulation functions */ /* EOF block manipulation functions */
bool xfs_can_free_eofblocks(struct xfs_inode *ip, bool force); bool xfs_can_free_eofblocks(struct xfs_inode *ip, bool force);
......
...@@ -805,44 +805,64 @@ xfs_file_aio_write( ...@@ -805,44 +805,64 @@ xfs_file_aio_write(
STATIC long STATIC long
xfs_file_fallocate( xfs_file_fallocate(
struct file *file, struct file *file,
int mode, int mode,
loff_t offset, loff_t offset,
loff_t len) loff_t len)
{ {
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
long error; struct xfs_inode *ip = XFS_I(inode);
loff_t new_size = 0; struct xfs_trans *tp;
xfs_flock64_t bf; long error;
xfs_inode_t *ip = XFS_I(inode); loff_t new_size = 0;
int cmd = XFS_IOC_RESVSP;
int attr_flags = 0;
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))
return -EOPNOTSUPP; return -EOPNOTSUPP;
bf.l_whence = 0;
bf.l_start = offset;
bf.l_len = len;
xfs_ilock(ip, XFS_IOLOCK_EXCL); xfs_ilock(ip, XFS_IOLOCK_EXCL);
if (mode & FALLOC_FL_PUNCH_HOLE) {
error = xfs_free_file_space(ip, offset, len);
if (error)
goto out_unlock;
} else {
if (!(mode & FALLOC_FL_KEEP_SIZE) &&
offset + len > i_size_read(inode)) {
new_size = offset + len;
error = -inode_newsize_ok(inode, new_size);
if (error)
goto out_unlock;
}
if (mode & FALLOC_FL_PUNCH_HOLE) error = xfs_alloc_file_space(ip, offset, len,
cmd = XFS_IOC_UNRESVSP; XFS_BMAPI_PREALLOC);
/* check the new inode size is valid before allocating */
if (!(mode & FALLOC_FL_KEEP_SIZE) &&
offset + len > i_size_read(inode)) {
new_size = offset + len;
error = inode_newsize_ok(inode, new_size);
if (error) if (error)
goto out_unlock; goto out_unlock;
} }
if (file->f_flags & O_DSYNC) tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_WRITEID);
attr_flags |= XFS_ATTR_SYNC; 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))
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);
error = -xfs_change_file_space(ip, cmd, &bf, 0, attr_flags); if (file->f_flags & O_DSYNC)
xfs_trans_set_sync(tp);
error = xfs_trans_commit(tp, 0);
if (error) if (error)
goto out_unlock; goto out_unlock;
...@@ -852,12 +872,12 @@ xfs_file_fallocate( ...@@ -852,12 +872,12 @@ xfs_file_fallocate(
iattr.ia_valid = ATTR_SIZE; iattr.ia_valid = ATTR_SIZE;
iattr.ia_size = new_size; iattr.ia_size = new_size;
error = -xfs_setattr_size(ip, &iattr); error = xfs_setattr_size(ip, &iattr);
} }
out_unlock: out_unlock:
xfs_iunlock(ip, XFS_IOLOCK_EXCL); xfs_iunlock(ip, XFS_IOLOCK_EXCL);
return error; return -error;
} }
......
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