|
@@ -2168,6 +2168,7 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
|
|
|
bool same_page = ((offset >> PAGE_CACHE_SHIFT) ==
|
|
|
((offset + len - 1) >> PAGE_CACHE_SHIFT));
|
|
|
bool no_holes = btrfs_fs_incompat(root->fs_info, NO_HOLES);
|
|
|
+ u64 ino_size = round_up(inode->i_size, PAGE_CACHE_SIZE);
|
|
|
|
|
|
ret = btrfs_wait_ordered_range(inode, offset, len);
|
|
|
if (ret)
|
|
@@ -2183,14 +2184,14 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
|
|
|
* entire page.
|
|
|
*/
|
|
|
if (same_page && len < PAGE_CACHE_SIZE) {
|
|
|
- if (offset < round_up(inode->i_size, PAGE_CACHE_SIZE))
|
|
|
+ if (offset < ino_size)
|
|
|
ret = btrfs_truncate_page(inode, offset, len, 0);
|
|
|
mutex_unlock(&inode->i_mutex);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
/* zero back part of the first page */
|
|
|
- if (offset < round_up(inode->i_size, PAGE_CACHE_SIZE)) {
|
|
|
+ if (offset < ino_size) {
|
|
|
ret = btrfs_truncate_page(inode, offset, 0, 0);
|
|
|
if (ret) {
|
|
|
mutex_unlock(&inode->i_mutex);
|
|
@@ -2199,7 +2200,7 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
|
|
|
}
|
|
|
|
|
|
/* zero the front end of the last page */
|
|
|
- if (offset + len < round_up(inode->i_size, PAGE_CACHE_SIZE)) {
|
|
|
+ if (offset + len < ino_size) {
|
|
|
ret = btrfs_truncate_page(inode, offset + len, 0, 1);
|
|
|
if (ret) {
|
|
|
mutex_unlock(&inode->i_mutex);
|
|
@@ -2288,10 +2289,13 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
|
|
|
|
|
|
trans->block_rsv = &root->fs_info->trans_block_rsv;
|
|
|
|
|
|
- ret = fill_holes(trans, inode, path, cur_offset, drop_end);
|
|
|
- if (ret) {
|
|
|
- err = ret;
|
|
|
- break;
|
|
|
+ if (cur_offset < ino_size) {
|
|
|
+ ret = fill_holes(trans, inode, path, cur_offset,
|
|
|
+ drop_end);
|
|
|
+ if (ret) {
|
|
|
+ err = ret;
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
cur_offset = drop_end;
|
|
@@ -2324,10 +2328,12 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
|
|
|
}
|
|
|
|
|
|
trans->block_rsv = &root->fs_info->trans_block_rsv;
|
|
|
- ret = fill_holes(trans, inode, path, cur_offset, drop_end);
|
|
|
- if (ret) {
|
|
|
- err = ret;
|
|
|
- goto out_trans;
|
|
|
+ if (cur_offset < ino_size) {
|
|
|
+ ret = fill_holes(trans, inode, path, cur_offset, drop_end);
|
|
|
+ if (ret) {
|
|
|
+ err = ret;
|
|
|
+ goto out_trans;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
out_trans:
|