diff options
Diffstat (limited to 'fs/overlayfs/file.c')
-rw-r--r-- | fs/overlayfs/file.c | 43 |
1 files changed, 24 insertions, 19 deletions
diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c index 986313da0c88..84dd957efa24 100644 --- a/fs/overlayfs/file.c +++ b/fs/overlayfs/file.c | |||
@@ -434,14 +434,14 @@ enum ovl_copyop { | |||
434 | OVL_DEDUPE, | 434 | OVL_DEDUPE, |
435 | }; | 435 | }; |
436 | 436 | ||
437 | static ssize_t ovl_copyfile(struct file *file_in, loff_t pos_in, | 437 | static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, |
438 | struct file *file_out, loff_t pos_out, | 438 | struct file *file_out, loff_t pos_out, |
439 | u64 len, unsigned int flags, enum ovl_copyop op) | 439 | loff_t len, unsigned int flags, enum ovl_copyop op) |
440 | { | 440 | { |
441 | struct inode *inode_out = file_inode(file_out); | 441 | struct inode *inode_out = file_inode(file_out); |
442 | struct fd real_in, real_out; | 442 | struct fd real_in, real_out; |
443 | const struct cred *old_cred; | 443 | const struct cred *old_cred; |
444 | ssize_t ret; | 444 | loff_t ret; |
445 | 445 | ||
446 | ret = ovl_real_fdget(file_out, &real_out); | 446 | ret = ovl_real_fdget(file_out, &real_out); |
447 | if (ret) | 447 | if (ret) |
@@ -462,12 +462,13 @@ static ssize_t ovl_copyfile(struct file *file_in, loff_t pos_in, | |||
462 | 462 | ||
463 | case OVL_CLONE: | 463 | case OVL_CLONE: |
464 | ret = vfs_clone_file_range(real_in.file, pos_in, | 464 | ret = vfs_clone_file_range(real_in.file, pos_in, |
465 | real_out.file, pos_out, len); | 465 | real_out.file, pos_out, len, flags); |
466 | break; | 466 | break; |
467 | 467 | ||
468 | case OVL_DEDUPE: | 468 | case OVL_DEDUPE: |
469 | ret = vfs_dedupe_file_range_one(real_in.file, pos_in, | 469 | ret = vfs_dedupe_file_range_one(real_in.file, pos_in, |
470 | real_out.file, pos_out, len); | 470 | real_out.file, pos_out, len, |
471 | flags); | ||
471 | break; | 472 | break; |
472 | } | 473 | } |
473 | revert_creds(old_cred); | 474 | revert_creds(old_cred); |
@@ -489,26 +490,31 @@ static ssize_t ovl_copy_file_range(struct file *file_in, loff_t pos_in, | |||
489 | OVL_COPY); | 490 | OVL_COPY); |
490 | } | 491 | } |
491 | 492 | ||
492 | static int ovl_clone_file_range(struct file *file_in, loff_t pos_in, | 493 | static loff_t ovl_remap_file_range(struct file *file_in, loff_t pos_in, |
493 | struct file *file_out, loff_t pos_out, u64 len) | 494 | struct file *file_out, loff_t pos_out, |
495 | loff_t len, unsigned int remap_flags) | ||
494 | { | 496 | { |
495 | return ovl_copyfile(file_in, pos_in, file_out, pos_out, len, 0, | 497 | enum ovl_copyop op; |
496 | OVL_CLONE); | 498 | |
497 | } | 499 | if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY)) |
500 | return -EINVAL; | ||
501 | |||
502 | if (remap_flags & REMAP_FILE_DEDUP) | ||
503 | op = OVL_DEDUPE; | ||
504 | else | ||
505 | op = OVL_CLONE; | ||
498 | 506 | ||
499 | static int ovl_dedupe_file_range(struct file *file_in, loff_t pos_in, | ||
500 | struct file *file_out, loff_t pos_out, u64 len) | ||
501 | { | ||
502 | /* | 507 | /* |
503 | * Don't copy up because of a dedupe request, this wouldn't make sense | 508 | * Don't copy up because of a dedupe request, this wouldn't make sense |
504 | * most of the time (data would be duplicated instead of deduplicated). | 509 | * most of the time (data would be duplicated instead of deduplicated). |
505 | */ | 510 | */ |
506 | if (!ovl_inode_upper(file_inode(file_in)) || | 511 | if (op == OVL_DEDUPE && |
507 | !ovl_inode_upper(file_inode(file_out))) | 512 | (!ovl_inode_upper(file_inode(file_in)) || |
513 | !ovl_inode_upper(file_inode(file_out)))) | ||
508 | return -EPERM; | 514 | return -EPERM; |
509 | 515 | ||
510 | return ovl_copyfile(file_in, pos_in, file_out, pos_out, len, 0, | 516 | return ovl_copyfile(file_in, pos_in, file_out, pos_out, len, |
511 | OVL_DEDUPE); | 517 | remap_flags, op); |
512 | } | 518 | } |
513 | 519 | ||
514 | const struct file_operations ovl_file_operations = { | 520 | const struct file_operations ovl_file_operations = { |
@@ -525,6 +531,5 @@ const struct file_operations ovl_file_operations = { | |||
525 | .compat_ioctl = ovl_compat_ioctl, | 531 | .compat_ioctl = ovl_compat_ioctl, |
526 | 532 | ||
527 | .copy_file_range = ovl_copy_file_range, | 533 | .copy_file_range = ovl_copy_file_range, |
528 | .clone_file_range = ovl_clone_file_range, | 534 | .remap_file_range = ovl_remap_file_range, |
529 | .dedupe_file_range = ovl_dedupe_file_range, | ||
530 | }; | 535 | }; |