summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-01-05 17:47:11 -0800
committerDarrick J. Wong <djwong@kernel.org>2021-03-25 17:08:52 -0700
commit8ab43fdb28b9afb92a0a6e5e9afa011acf179f4c (patch)
tree03192b027c149d6e8b994c50a1cc7e0ed80ba017 /fs
parentc579fc72bbc704b86e2c669cf930ccafb62fc003 (diff)
vfs: explicitly pass the block size to the remap prep function
Make it so that filesystems can pass an explicit blocksize to the remap prep function. This enables filesystems whose fundamental allocation units are /not/ the same as the blocksize to ensure that the remapping checks are aligned properly. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/remap_range.c37
1 files changed, 24 insertions, 13 deletions
diff --git a/fs/remap_range.c b/fs/remap_range.c
index 1a0bbd73106e..487d0024d68c 100644
--- a/fs/remap_range.c
+++ b/fs/remap_range.c
@@ -28,18 +28,18 @@
*/
static int generic_remap_checks(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out,
- loff_t *req_count, unsigned int remap_flags)
+ loff_t *req_count, unsigned int remap_flags,
+ unsigned int blocksize)
{
struct inode *inode_in = file_in->f_mapping->host;
struct inode *inode_out = file_out->f_mapping->host;
uint64_t count = *req_count;
uint64_t bcount;
loff_t size_in, size_out;
- loff_t bs = inode_out->i_sb->s_blocksize;
int ret;
/* The start of both ranges must be aligned to an fs block. */
- if (!IS_ALIGNED(pos_in, bs) || !IS_ALIGNED(pos_out, bs))
+ if (!IS_ALIGNED(pos_in, blocksize) || !IS_ALIGNED(pos_out, blocksize))
return -EINVAL;
/* Ensure offsets don't wrap. */
@@ -72,10 +72,10 @@ static int generic_remap_checks(struct file *file_in, loff_t pos_in,
* already confirmed the starting offsets' block alignment.
*/
if (pos_in + count == size_in) {
- bcount = ALIGN(size_in, bs) - pos_in;
+ bcount = ALIGN(size_in, blocksize) - pos_in;
} else {
- if (!IS_ALIGNED(count, bs))
- count = ALIGN_DOWN(count, bs);
+ if (!IS_ALIGNED(count, blocksize))
+ count = ALIGN_DOWN(count, blocksize);
bcount = count;
}
@@ -135,9 +135,10 @@ static int generic_remap_check_len(struct inode *inode_in,
struct inode *inode_out,
loff_t pos_out,
loff_t *len,
- unsigned int remap_flags)
+ unsigned int remap_flags,
+ unsigned int blocksize)
{
- u64 blkmask = i_blocksize(inode_in) - 1;
+ u64 blkmask = blocksize - 1;
loff_t new_len = *len;
if ((*len & blkmask) == 0)
@@ -289,9 +290,9 @@ out_error:
* If there's an error, then the usual negative error code is returned.
* Otherwise returns 0 with *len set to the request length.
*/
-int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
- struct file *file_out, loff_t pos_out,
- loff_t *len, unsigned int remap_flags)
+int __generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
+ struct file *file_out, loff_t pos_out, loff_t *len,
+ unsigned int remap_flags, unsigned int blocksize)
{
struct inode *inode_in = file_inode(file_in);
struct inode *inode_out = file_inode(file_out);
@@ -326,7 +327,7 @@ int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
/* Check that we don't violate system file offset limits. */
ret = generic_remap_checks(file_in, pos_in, file_out, pos_out, len,
- remap_flags);
+ remap_flags, blocksize);
if (ret)
return ret;
@@ -360,7 +361,7 @@ int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
}
ret = generic_remap_check_len(inode_in, inode_out, pos_out, len,
- remap_flags);
+ remap_flags, blocksize);
if (ret)
return ret;
@@ -370,6 +371,16 @@ int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
return ret;
}
+EXPORT_SYMBOL(__generic_remap_file_range_prep);
+
+int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
+ struct file *file_out, loff_t pos_out, loff_t *len,
+ unsigned int remap_flags)
+{
+ return __generic_remap_file_range_prep(file_in, pos_in, file_out,
+ pos_out, len, remap_flags,
+ file_inode(file_out)->i_sb->s_blocksize);
+}
EXPORT_SYMBOL(generic_remap_file_range_prep);
loff_t do_clone_file_range(struct file *file_in, loff_t pos_in,