Project

General

Profile

Feature #13867 ยป patch2.diff

use copy_file_range(2) without keyword arguments - Glass_saga (Masaki Matsushita), 10/21/2017 06:26 AM

View differences:

io.c
10489 10489
    return 0;
10490 10490
}
10491 10491

  
10492
#if defined __linux__ && defined __NR_copy_file_range
10493
#  define USE_COPY_FILE_RANGE
10494
#endif
10495

  
10496
#ifdef USE_COPY_FILE_RANGE
10497

  
10498
static ssize_t
10499
simple_copy_file_range(int in_fd, off_t *in_offset, int out_fd, off_t *out_offset, size_t count, unsigned int flags)
10500
{
10501
    return syscall(__NR_copy_file_range, in_fd, in_offset, out_fd, out_offset, count, flags);
10502
}
10503

  
10504
static int
10505
nogvl_copy_file_range(struct copy_stream_struct *stp)
10506
{
10507
    struct stat src_stat, dst_stat;
10508
    ssize_t ss;
10509
    int ret;
10510

  
10511
    off_t copy_length, src_offset, *src_offset_ptr;
10512

  
10513
    ret = fstat(stp->src_fd, &src_stat);
10514
    if (ret == -1) {
10515
        stp->syserr = "fstat";
10516
        stp->error_no = errno;
10517
        return -1;
10518
    }
10519
    if (!S_ISREG(src_stat.st_mode))
10520
        return 0;
10521

  
10522
    ret = fstat(stp->dst_fd, &dst_stat);
10523
    if (ret == -1) {
10524
        stp->syserr = "fstat";
10525
        stp->error_no = errno;
10526
        return -1;
10527
    }
10528

  
10529
    src_offset = stp->src_offset;
10530
    if (src_offset != (off_t)-1) {
10531
	src_offset_ptr = &src_offset;
10532
    }
10533
    else {
10534
	src_offset_ptr = NULL; /* if src_offset_ptr is NULL, then bytes are read from in_fd starting from the file offset */
10535
    }
10536

  
10537
    copy_length = stp->copy_length;
10538
    if (copy_length == (off_t)-1) {
10539
	if (src_offset == (off_t)-1) {
10540
	    off_t current_offset;
10541
            errno = 0;
10542
            current_offset = lseek(stp->src_fd, 0, SEEK_CUR);
10543
            if (current_offset == (off_t)-1 && errno) {
10544
                stp->syserr = "lseek";
10545
                stp->error_no = errno;
10546
                return -1;
10547
            }
10548
	    copy_length = src_stat.st_size - current_offset;
10549
	}
10550
	else {
10551
	    copy_length = src_stat.st_size - src_offset;
10552
	}
10553
    }
10554

  
10555
  retry_copy_file_range:
10556
# if SIZEOF_OFF_T > SIZEOF_SIZE_T
10557
    /* we are limited by the 32-bit ssize_t return value on 32-bit */
10558
    ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
10559
# else
10560
    ss = (ssize_t)copy_length;
10561
# endif
10562
    ss = simple_copy_file_range(stp->src_fd, src_offset_ptr, stp->dst_fd, NULL, ss, 0);
10563
    if (0 < ss) {
10564
        stp->total += ss;
10565
        copy_length -= ss;
10566
        if (0 < copy_length) {
10567
            goto retry_copy_file_range;
10568
        }
10569
    }
10570
    if (ss == -1) {
10571
	if (maygvl_copy_stream_continue_p(0, stp)) {
10572
            goto retry_copy_file_range;
10573
	}
10574
        switch (errno) {
10575
	  case EINVAL:
10576
#ifdef ENOSYS
10577
	  case ENOSYS:
10578
#endif
10579
#ifdef EXDEV
10580
	  case EXDEV: /* in_fd and out_fd are not on the same filesystem */
10581
#endif
10582
            return 0;
10583
	  case EAGAIN:
10584
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
10585
	  case EWOULDBLOCK:
10586
#endif
10587
            if (nogvl_copy_stream_wait_write(stp) == -1)
10588
                return -1;
10589
            goto retry_copy_file_range;
10590
        }
10591
        stp->syserr = "copy_file_range";
10592
        stp->error_no = errno;
10593
        return -1;
10594
    }
10595
    return 1;
10596
}
10597
#endif
10598

  
10492 10599
#ifdef HAVE_SENDFILE
10493 10600

  
10494 10601
# ifdef __linux__
......
10787 10894
    int ret;
10788 10895
#endif
10789 10896

  
10897
#ifdef USE_COPY_FILE_RANGE
10898
    ret = nogvl_copy_file_range(stp);
10899
    if (ret != 0)
10900
	goto finish; /* error or success */
10901
#endif
10902

  
10790 10903
#ifdef USE_SENDFILE
10791 10904
    ret = nogvl_copy_stream_sendfile(stp);
10792 10905
    if (ret != 0)