static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len) { pgoff_t pg_start, pg_end; loff_t new_size; int ret; if (offset + len >= i_size_read(inode)) return -EINVAL; /* collapse range should be aligned to block size of f2fs. */ if (offset & (F2FS_BLKSIZE - 1) || len & (F2FS_BLKSIZE - 1)) return -EINVAL; f2fs_balance_fs(F2FS_I_SB(inode)); if (f2fs_has_inline_data(inode)) { ret = f2fs_convert_inline_inode(inode); if (ret) return ret; } pg_start = offset >> PAGE_CACHE_SHIFT; pg_end = (offset + len) >> PAGE_CACHE_SHIFT; /* write out all dirty pages from offset */ ret = filemap_write_and_wait_range(inode->i_mapping, offset, LLONG_MAX); if (ret) return ret; truncate_pagecache(inode, 0, offset); ret = f2fs_do_collapse(inode, pg_start, pg_end); if (ret) return ret; /* write out all moved pages, if possible */ filemap_write_and_wait_range(inode->i_mapping, offset, LLONG_MAX); truncate_pagecache(inode, 0, offset); new_size = i_size_read(inode) - len; truncate_pagecache(inode, 0, new_size); ret = truncate_blocks(inode, new_size, true); if (!ret) i_size_write(inode, new_size); return ret; }
static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len) { pgoff_t pg_start, pg_end; loff_t new_size; int ret; if (!S_ISREG(inode->i_mode)) return -EINVAL; if (offset + len >= i_size_read(inode)) return -EINVAL; /* collapse range should be aligned to block size of f2fs. */ if (offset & (F2FS_BLKSIZE - 1) || len & (F2FS_BLKSIZE - 1)) return -EINVAL; pg_start = offset >> PAGE_CACHE_SHIFT; pg_end = (offset + len) >> PAGE_CACHE_SHIFT; /* write out all dirty pages from offset */ ret = filemap_write_and_wait_range(inode->i_mapping, offset, LLONG_MAX); if (ret) return ret; truncate_pagecache(inode, offset); ret = f2fs_do_collapse(inode, pg_start, pg_end); if (ret) return ret; new_size = i_size_read(inode) - len; ret = truncate_blocks(inode, new_size, true); if (!ret) i_size_write(inode, new_size); return ret; }