Lines 3096-3108
vn_generic_copy_file_range(struct vnode *invp, off_t *
Link Here
|
3096 |
struct vnode *outvp, off_t *outoffp, size_t *lenp, unsigned int flags, |
3096 |
struct vnode *outvp, off_t *outoffp, size_t *lenp, unsigned int flags, |
3097 |
struct ucred *incred, struct ucred *outcred, struct thread *fsize_td) |
3097 |
struct ucred *incred, struct ucred *outcred, struct thread *fsize_td) |
3098 |
{ |
3098 |
{ |
3099 |
struct vattr va; |
3099 |
struct vattr va, inva; |
3100 |
struct mount *mp; |
3100 |
struct mount *mp; |
3101 |
struct uio io; |
3101 |
struct uio io; |
3102 |
off_t startoff, endoff, xfer, xfer2; |
3102 |
off_t startoff, endoff, xfer, xfer2; |
3103 |
u_long blksize; |
3103 |
u_long blksize; |
3104 |
int error, interrupted; |
3104 |
int error, interrupted; |
3105 |
bool cantseek, readzeros, eof, lastblock; |
3105 |
bool cantseek, readzeros, eof, lastblock, holetoeof; |
3106 |
ssize_t aresid; |
3106 |
ssize_t aresid; |
3107 |
size_t copylen, len, rem, savlen; |
3107 |
size_t copylen, len, rem, savlen; |
3108 |
char *dat; |
3108 |
char *dat; |
Lines 3119-3125
vn_generic_copy_file_range(struct vnode *invp, off_t *
Link Here
|
3119 |
goto out; |
3119 |
goto out; |
3120 |
if (VOP_PATHCONF(invp, _PC_MIN_HOLE_SIZE, &holein) != 0) |
3120 |
if (VOP_PATHCONF(invp, _PC_MIN_HOLE_SIZE, &holein) != 0) |
3121 |
holein = 0; |
3121 |
holein = 0; |
|
|
3122 |
if (holein > 0) |
3123 |
error = VOP_GETATTR(invp, &inva, incred); |
3122 |
VOP_UNLOCK(invp); |
3124 |
VOP_UNLOCK(invp); |
|
|
3125 |
if (error != 0) |
3126 |
goto out; |
3123 |
|
3127 |
|
3124 |
mp = NULL; |
3128 |
mp = NULL; |
3125 |
error = vn_start_write(outvp, &mp, V_WAIT); |
3129 |
error = vn_start_write(outvp, &mp, V_WAIT); |
Lines 3200-3206
vn_generic_copy_file_range(struct vnode *invp, off_t *
Link Here
|
3200 |
* Note that some file systems such as NFSv3, NFSv4.0 and NFSv4.1 may |
3204 |
* Note that some file systems such as NFSv3, NFSv4.0 and NFSv4.1 may |
3201 |
* support holes on the server, but do not support FIOSEEKHOLE. |
3205 |
* support holes on the server, but do not support FIOSEEKHOLE. |
3202 |
*/ |
3206 |
*/ |
3203 |
eof = false; |
3207 |
holetoeof = eof = false; |
3204 |
while (len > 0 && error == 0 && !eof && interrupted == 0) { |
3208 |
while (len > 0 && error == 0 && !eof && interrupted == 0) { |
3205 |
endoff = 0; /* To shut up compilers. */ |
3209 |
endoff = 0; /* To shut up compilers. */ |
3206 |
cantseek = true; |
3210 |
cantseek = true; |
Lines 3209-3216
vn_generic_copy_file_range(struct vnode *invp, off_t *
Link Here
|
3209 |
|
3213 |
|
3210 |
/* |
3214 |
/* |
3211 |
* Find the next data area. If there is just a hole to EOF, |
3215 |
* Find the next data area. If there is just a hole to EOF, |
3212 |
* FIOSEEKDATA should fail and then we drop down into the |
3216 |
* FIOSEEKDATA should fail with ENXIO. |
3213 |
* inner loop and create the hole on the outvp file. |
|
|
3214 |
* (I do not know if any file system will report a hole to |
3217 |
* (I do not know if any file system will report a hole to |
3215 |
* EOF via FIOSEEKHOLE, but I am pretty sure FIOSEEKDATA |
3218 |
* EOF via FIOSEEKHOLE, but I am pretty sure FIOSEEKDATA |
3216 |
* will fail for those file systems.) |
3219 |
* will fail for those file systems.) |
Lines 3219-3228
vn_generic_copy_file_range(struct vnode *invp, off_t *
Link Here
|
3219 |
* the code just falls through to the inner copy loop. |
3222 |
* the code just falls through to the inner copy loop. |
3220 |
*/ |
3223 |
*/ |
3221 |
error = EINVAL; |
3224 |
error = EINVAL; |
3222 |
if (holein > 0) |
3225 |
if (holein > 0) { |
3223 |
error = VOP_IOCTL(invp, FIOSEEKDATA, &startoff, 0, |
3226 |
error = VOP_IOCTL(invp, FIOSEEKDATA, &startoff, 0, |
3224 |
incred, curthread); |
3227 |
incred, curthread); |
3225 |
if (error == 0) { |
3228 |
if (error == ENXIO) { |
|
|
3229 |
startoff = endoff = inva.va_size; |
3230 |
eof = holetoeof = true; |
3231 |
error = 0; |
3232 |
} |
3233 |
} |
3234 |
if (error == 0 && !holetoeof) { |
3226 |
endoff = startoff; |
3235 |
endoff = startoff; |
3227 |
error = VOP_IOCTL(invp, FIOSEEKHOLE, &endoff, 0, |
3236 |
error = VOP_IOCTL(invp, FIOSEEKHOLE, &endoff, 0, |
3228 |
incred, curthread); |
3237 |
incred, curthread); |
Lines 3253-3263
vn_generic_copy_file_range(struct vnode *invp, off_t *
Link Here
|
3253 |
} |
3262 |
} |
3254 |
|
3263 |
|
3255 |
if (error == 0 && *outoffp + xfer > |
3264 |
if (error == 0 && *outoffp + xfer > |
3256 |
va.va_size && xfer == len) |
3265 |
va.va_size && (xfer == len || holetoeof)) { |
3257 |
/* Grow last block. */ |
3266 |
/* Grow output file (hole at end). */ |
3258 |
error = vn_write_outvp(outvp, dat, |
3267 |
error = vn_write_outvp(outvp, dat, |
3259 |
*outoffp, xfer, blksize, true, |
3268 |
*outoffp, xfer, blksize, true, |
3260 |
false, outcred); |
3269 |
false, outcred); |
|
|
3270 |
} |
3261 |
if (error == 0) { |
3271 |
if (error == 0) { |
3262 |
*inoffp += xfer; |
3272 |
*inoffp += xfer; |
3263 |
*outoffp += xfer; |
3273 |
*outoffp += xfer; |