Changeset View
Standalone View
sys/kern/vfs_vnops.c.sav2
Show First 20 Lines • Show All 3,006 Lines • ▼ Show 20 Lines | vn_generic_copy_file_range(struct vnode *invp, off_t *inoffp, | |||||||||||
off_t startoff, endoff, xfer, xfer2; | off_t startoff, endoff, xfer, xfer2; | |||||||||||
u_long blksize; | u_long blksize; | |||||||||||
int error; | int error; | |||||||||||
bool cantseek, readzeros, eof, lastblock; | bool cantseek, readzeros, eof, lastblock; | |||||||||||
ssize_t aresid; | ssize_t aresid; | |||||||||||
size_t copylen, len, savlen; | size_t copylen, len, savlen; | |||||||||||
char *dat; | char *dat; | |||||||||||
long holein, holeout; | long holein, holeout; | |||||||||||
uint64_t curtime, stoptime; | ||||||||||||
struct timespec tm; | ||||||||||||
nanouptime(&tm); | ||||||||||||
stoptime = tm.tv_sec + 1; | ||||||||||||
stoptime = stoptime * 1000000000 + tm.tv_nsec; | ||||||||||||
asomers: Why don't you define `curtime` and `stoptime` in terms of nanoseconds instead of microseconds? | ||||||||||||
rmacklemAuthorUnsubmitted Done Inline ActionsI, personally, do not think that a micro-optimization However, I agree that it makes the code simpler to rmacklem: I, personally, do not think that a micro-optimization
like saving a "divide instruction" is… | ||||||||||||
curtime = 0; | ||||||||||||
holein = holeout = 0; | holein = holeout = 0; | |||||||||||
savlen = len = *lenp; | savlen = len = *lenp; | |||||||||||
error = 0; | error = 0; | |||||||||||
dat = NULL; | dat = NULL; | |||||||||||
error = vn_lock(invp, LK_SHARED); | error = vn_lock(invp, LK_SHARED); | |||||||||||
if (error != 0) | if (error != 0) | |||||||||||
goto out; | goto out; | |||||||||||
▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | #endif | |||||||||||
/* | /* | |||||||||||
* If VOP_IOCTL(FIOSEEKHOLE) works for invp, use it and FIOSEEKDATA | * If VOP_IOCTL(FIOSEEKHOLE) works for invp, use it and FIOSEEKDATA | |||||||||||
* to find holes. Otherwise, just scan the read block for all 0s | * to find holes. Otherwise, just scan the read block for all 0s | |||||||||||
* in the inner loop where the data copying is done. | * in the inner loop where the data copying is done. | |||||||||||
* Note that some file systems such as NFSv3, NFSv4.0 and NFSv4.1 may | * Note that some file systems such as NFSv3, NFSv4.0 and NFSv4.1 may | |||||||||||
* support holes on the server, but do not support FIOSEEKHOLE. | * support holes on the server, but do not support FIOSEEKHOLE. | |||||||||||
*/ | */ | |||||||||||
eof = false; | eof = false; | |||||||||||
Done Inline ActionsSince this 1-second timeout is only a goal, not a hard limit, I suggest removing the check here and just relying on the inner check. asomers: Since this 1-second timeout is only a goal, not a hard limit, I suggest removing the check here… | ||||||||||||
rmacklemAuthorUnsubmitted Done Inline ActionsIt would simply loop here without the check. I'll assume that is what you meant. rmacklem: It would simply loop here without the check.
However, I do agree that updating curtime here
was… | ||||||||||||
asomersUnsubmitted Not Done Inline ActionsYes asomers: Yes | ||||||||||||
while (len > 0 && error == 0 && !eof) { | while (len > 0 && error == 0 && !eof && curtime < stoptime) { | |||||||||||
endoff = 0; /* To shut up compilers. */ | endoff = 0; /* To shut up compilers. */ | |||||||||||
cantseek = true; | cantseek = true; | |||||||||||
startoff = *inoffp; | startoff = *inoffp; | |||||||||||
copylen = len; | copylen = len; | |||||||||||
/* | /* | |||||||||||
* Find the next data area. If there is just a hole to EOF, | * Find the next data area. If there is just a hole to EOF, | |||||||||||
* FIOSEEKDATA should fail and then we drop down into the | * FIOSEEKDATA should fail and then we drop down into the | |||||||||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | if (error == 0) { | |||||||||||
/* Grow last block. */ | /* Grow last block. */ | |||||||||||
error = vn_write_outvp(outvp, dat, | error = vn_write_outvp(outvp, dat, | |||||||||||
*outoffp, xfer, blksize, true, | *outoffp, xfer, blksize, true, | |||||||||||
false, outcred); | false, outcred); | |||||||||||
if (error == 0) { | if (error == 0) { | |||||||||||
*inoffp += xfer; | *inoffp += xfer; | |||||||||||
*outoffp += xfer; | *outoffp += xfer; | |||||||||||
len -= xfer; | len -= xfer; | |||||||||||
nanouptime(&tm); | ||||||||||||
curtime = tm.tv_sec; | ||||||||||||
curtime = curtime * 1000000000 + | ||||||||||||
tm.tv_nsec; | ||||||||||||
} | } | |||||||||||
} | } | |||||||||||
copylen = MIN(len, endoff - startoff); | copylen = MIN(len, endoff - startoff); | |||||||||||
cantseek = false; | cantseek = false; | |||||||||||
} else { | } else { | |||||||||||
cantseek = true; | cantseek = true; | |||||||||||
startoff = *inoffp; | startoff = *inoffp; | |||||||||||
copylen = len; | copylen = len; | |||||||||||
error = 0; | error = 0; | |||||||||||
} | } | |||||||||||
xfer = blksize; | xfer = blksize; | |||||||||||
if (cantseek) { | if (cantseek) { | |||||||||||
/* | /* | |||||||||||
* Set first xfer to end at a block boundary, so that | * Set first xfer to end at a block boundary, so that | |||||||||||
* holes are more likely detected in the loop below via | * holes are more likely detected in the loop below via | |||||||||||
* the for all bytes 0 method. | * the for all bytes 0 method. | |||||||||||
*/ | */ | |||||||||||
xfer -= (*inoffp % blksize); | xfer -= (*inoffp % blksize); | |||||||||||
} | } | |||||||||||
/* Loop copying the data block. */ | /* Loop copying the data block. */ | |||||||||||
while (copylen > 0 && error == 0 && !eof) { | while (copylen > 0 && error == 0 && !eof && | |||||||||||
curtime < stoptime) { | ||||||||||||
if (copylen < xfer) | if (copylen < xfer) | |||||||||||
xfer = copylen; | xfer = copylen; | |||||||||||
error = vn_lock(invp, LK_SHARED); | error = vn_lock(invp, LK_SHARED); | |||||||||||
if (error != 0) | if (error != 0) | |||||||||||
goto out; | goto out; | |||||||||||
error = vn_rdwr(UIO_READ, invp, dat, xfer, | error = vn_rdwr(UIO_READ, invp, dat, xfer, | |||||||||||
startoff, UIO_SYSSPACE, IO_NODELOCKED, | startoff, UIO_SYSSPACE, IO_NODELOCKED, | |||||||||||
curthread->td_ucred, incred, &aresid, | curthread->td_ucred, incred, &aresid, | |||||||||||
Show All 27 Lines | while (copylen > 0 && error == 0 && !eof && | |||||||||||
*inoffp += xfer; | *inoffp += xfer; | |||||||||||
startoff += xfer; | startoff += xfer; | |||||||||||
*outoffp += xfer; | *outoffp += xfer; | |||||||||||
copylen -= xfer; | copylen -= xfer; | |||||||||||
len -= xfer; | len -= xfer; | |||||||||||
} | } | |||||||||||
} | } | |||||||||||
xfer = blksize; | xfer = blksize; | |||||||||||
nanouptime(&tm); | ||||||||||||
curtime = tm.tv_sec; | ||||||||||||
curtime = curtime * 1000000000 + tm.tv_nsec; | ||||||||||||
} | } | |||||||||||
} | } | |||||||||||
out: | out: | |||||||||||
*lenp = savlen - len; | *lenp = savlen - len; | |||||||||||
free(dat, M_TEMP); | free(dat, M_TEMP); | |||||||||||
return (error); | return (error); | |||||||||||
asomersUnsubmitted Not Done Inline Actions
I think the latest version fixes the risk of returning EOF due to timer expiry. But I would still be tempted to add an assertion to guarantee it. asomers: I think the latest version fixes the risk of returning EOF due to timer expiry. But I would… | ||||||||||||
} | } | |||||||||||
static int | static int | |||||||||||
vn_fallocate(struct file *fp, off_t offset, off_t len, struct thread *td) | vn_fallocate(struct file *fp, off_t offset, off_t len, struct thread *td) | |||||||||||
{ | { | |||||||||||
struct mount *mp; | struct mount *mp; | |||||||||||
struct vnode *vp; | struct vnode *vp; | |||||||||||
off_t olen, ooffset; | off_t olen, ooffset; | |||||||||||
▲ Show 20 Lines • Show All 50 Lines • Show Last 20 Lines |
Why don't you define curtime and stoptime in terms of nanoseconds instead of microseconds? That would save some division instructions.