Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 339445
b: refs/heads/master
c: ef9d873
h: refs/heads/master
i:
  339443: 670d829
v: v3
  • Loading branch information
Dave Chinner authored and Ben Myers committed Nov 29, 2012
1 parent 2b858c7 commit 7a31655
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 23 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7c4cebe8e02dd0b0e655605442bbe9268db9ed4f
refs/heads/master: ef9d873344ff9f5084eacb9f3735982314dfda9e
2 changes: 1 addition & 1 deletion trunk/fs/xfs/xfs_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ xfs_rw_ilock_demote(
* valid before the operation, it will be read from disk before
* being partially zeroed.
*/
STATIC int
int
xfs_iozero(
struct xfs_inode *ip, /* inode */
loff_t pos, /* offset in file */
Expand Down
96 changes: 75 additions & 21 deletions trunk/fs/xfs/xfs_vnodeops.c
Original file line number Diff line number Diff line change
Expand Up @@ -2095,6 +2095,73 @@ xfs_free_file_space(
return error;
}


STATIC int
xfs_zero_file_space(
struct xfs_inode *ip,
xfs_off_t offset,
xfs_off_t len,
int attr_flags)
{
struct xfs_mount *mp = ip->i_mount;
uint granularity;
xfs_off_t start_boundary;
xfs_off_t end_boundary;
int error;

granularity = max_t(uint, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE);

/*
* Round the range of extents we are going to convert inwards. If the
* offset is aligned, then it doesn't get changed so we zero from the
* start of the block offset points to.
*/
start_boundary = round_up(offset, granularity);
end_boundary = round_down(offset + len, granularity);

ASSERT(start_boundary >= offset);
ASSERT(end_boundary <= offset + len);

if (!(attr_flags & XFS_ATTR_NOLOCK))
xfs_ilock(ip, XFS_IOLOCK_EXCL);

if (start_boundary < end_boundary - 1) {
/* punch out the page cache over the conversion range */
truncate_pagecache_range(VFS_I(ip), start_boundary,
end_boundary - 1);
/* convert the blocks */
error = xfs_alloc_file_space(ip, start_boundary,
end_boundary - start_boundary - 1,
XFS_BMAPI_PREALLOC | XFS_BMAPI_CONVERT,
attr_flags);
if (error)
goto out_unlock;

/* We've handled the interior of the range, now for the edges */
if (start_boundary != offset)
error = xfs_iozero(ip, offset, start_boundary - offset);
if (error)
goto out_unlock;

if (end_boundary != offset + len)
error = xfs_iozero(ip, end_boundary,
offset + len - end_boundary);

} else {
/*
* It's either a sub-granularity range or the range spanned lies
* partially across two adjacent blocks.
*/
error = xfs_iozero(ip, offset, len);
}

out_unlock:
if (!(attr_flags & XFS_ATTR_NOLOCK))
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
return error;

}

/*
* xfs_change_file_space()
* This routine allocates or frees disk space for the given file.
Expand All @@ -2120,10 +2187,8 @@ xfs_change_file_space(
xfs_fsize_t fsize;
int setprealloc;
xfs_off_t startoffset;
xfs_off_t end;
xfs_trans_t *tp;
struct iattr iattr;
int prealloc_type;

if (!S_ISREG(ip->i_d.di_mode))
return XFS_ERROR(EINVAL);
Expand Down Expand Up @@ -2172,31 +2237,20 @@ xfs_change_file_space(
startoffset = bf->l_start;
fsize = XFS_ISIZE(ip);

/*
* XFS_IOC_RESVSP and XFS_IOC_UNRESVSP will reserve or unreserve
* file space.
* These calls do NOT zero the data space allocated to the file,
* nor do they change the file size.
*
* XFS_IOC_ALLOCSP and XFS_IOC_FREESP will allocate and free file
* space.
* These calls cause the new file data to be zeroed and the file
* size to be changed.
*/
setprealloc = clrprealloc = 0;
prealloc_type = XFS_BMAPI_PREALLOC;

switch (cmd) {
case XFS_IOC_ZERO_RANGE:
prealloc_type |= XFS_BMAPI_CONVERT;
end = round_down(startoffset + bf->l_len, PAGE_SIZE) - 1;
if (startoffset <= end)
truncate_pagecache_range(VFS_I(ip), startoffset, end);
/* FALLTHRU */
error = xfs_zero_file_space(ip, startoffset, bf->l_len,
attr_flags);
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,
prealloc_type, attr_flags);
XFS_BMAPI_PREALLOC, attr_flags);
if (error)
return error;
setprealloc = 1;
Expand Down
1 change: 1 addition & 0 deletions trunk/fs/xfs/xfs_vnodeops.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags);
int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
int flags, struct attrlist_cursor_kern *cursor);

int xfs_iozero(struct xfs_inode *, loff_t, size_t);
int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t);
int xfs_free_eofblocks(struct xfs_mount *, struct xfs_inode *, bool);

Expand Down

0 comments on commit 7a31655

Please sign in to comment.