View | Details | Raw Unified | Return to bug 255523 | Differences between
and this patch

Collapse All | Expand All

(-)sys/kern/vfs_vnops.c (-9 / +19 lines)
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;

Return to bug 255523