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

Collapse All | Expand All

(-)sys/kern/vfs_vnops.c (-8 / +26 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 3115-3120 vn_generic_copy_file_range(struct vnode *invp, off_t * Link Here
3115
	dat = NULL;
3115
	dat = NULL;
3116
3116
3117
	error = vn_lock(invp, LK_SHARED);
3117
	error = vn_lock(invp, LK_SHARED);
3118
	if (error == 0)
3119
		error = VOP_GETATTR(invp, &inva, incred);
3118
	if (error != 0)
3120
	if (error != 0)
3119
		goto out;
3121
		goto out;
3120
	if (VOP_PATHCONF(invp, _PC_MIN_HOLE_SIZE, &holein) != 0)
3122
	if (VOP_PATHCONF(invp, _PC_MIN_HOLE_SIZE, &holein) != 0)
Lines 3209-3216 vn_generic_copy_file_range(struct vnode *invp, off_t * Link Here
3209
3211
3210
		/*
3212
		/*
3211
		 * Find the next data area.  If there is just a hole to EOF,
3213
		 * Find the next data area.  If there is just a hole to EOF,
3212
		 * FIOSEEKDATA should fail and then we drop down into the
3214
		 * 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
3215
		 * (I do not know if any file system will report a hole to
3215
		 *  EOF via FIOSEEKHOLE, but I am pretty sure FIOSEEKDATA
3216
		 *  EOF via FIOSEEKHOLE, but I am pretty sure FIOSEEKDATA
3216
		 *  will fail for those file systems.)
3217
		 *  will fail for those file systems.)
Lines 3219-3231 vn_generic_copy_file_range(struct vnode *invp, off_t * Link Here
3219
		 * the code just falls through to the inner copy loop.
3220
		 * the code just falls through to the inner copy loop.
3220
		 */
3221
		 */
3221
		error = EINVAL;
3222
		error = EINVAL;
3222
		if (holein > 0)
3223
		holetoeof = false;
3224
		if (holein > 0) {
3223
			error = VOP_IOCTL(invp, FIOSEEKDATA, &startoff, 0,
3225
			error = VOP_IOCTL(invp, FIOSEEKDATA, &startoff, 0,
3224
			    incred, curthread);
3226
			    incred, curthread);
3225
		if (error == 0) {
3227
printf("seekdata soff=%ld err=%d\n", startoff, error);
3228
			if (error == ENXIO) {
3229
				startoff = endoff = inva.va_size;
3230
				eof = holetoeof = true;
3231
printf("holeeof\n");
3232
				error = 0;
3233
			}
3234
		}
3235
		if (error == 0 && !holetoeof) {
3226
			endoff = startoff;
3236
			endoff = startoff;
3227
			error = VOP_IOCTL(invp, FIOSEEKHOLE, &endoff, 0,
3237
			error = VOP_IOCTL(invp, FIOSEEKHOLE, &endoff, 0,
3228
			    incred, curthread);
3238
			    incred, curthread);
3239
printf("seekhole eoff=%ld err=%d\n", endoff, error);
3229
			/*
3240
			/*
3230
			 * Since invp is unlocked, it may be possible for
3241
			 * Since invp is unlocked, it may be possible for
3231
			 * another thread to do a truncate(), lseek(), write()
3242
			 * another thread to do a truncate(), lseek(), write()
Lines 3240-3248 vn_generic_copy_file_range(struct vnode *invp, off_t * Link Here
3240
		}
3251
		}
3241
		if (error == 0) {
3252
		if (error == 0) {
3242
			if (startoff > *inoffp) {
3253
			if (startoff > *inoffp) {
3254
printf("hole at startoff\n");
3243
				/* Found hole before data block. */
3255
				/* Found hole before data block. */
3244
				xfer = MIN(startoff - *inoffp, len);
3256
				xfer = MIN(startoff - *inoffp, len);
3257
printf("xfer=%ld len=%ld\n", xfer, len);
3245
				if (*outoffp < va.va_size) {
3258
				if (*outoffp < va.va_size) {
3259
printf("punching hole\n");
3246
					/* Must write 0s to punch hole. */
3260
					/* Must write 0s to punch hole. */
3247
					xfer2 = MIN(va.va_size - *outoffp,
3261
					xfer2 = MIN(va.va_size - *outoffp,
3248
					    xfer);
3262
					    xfer);
Lines 3253-3267 vn_generic_copy_file_range(struct vnode *invp, off_t * Link Here
3253
				}
3267
				}
3254
3268
3255
				if (error == 0 && *outoffp + xfer >
3269
				if (error == 0 && *outoffp + xfer >
3256
				    va.va_size && xfer == len)
3270
				    va.va_size && (xfer == len || holetoeof)) {
3257
					/* Grow last block. */
3271
					/* Grow output file (hole at end). */
3258
					error = vn_write_outvp(outvp, dat,
3272
					error = vn_write_outvp(outvp, dat,
3259
					    *outoffp, xfer, blksize, true,
3273
					    *outoffp, xfer, blksize, true,
3260
					    false, outcred);
3274
					    false, outcred);
3275
printf("grow at end=%d\n", error);
3276
				}
3261
				if (error == 0) {
3277
				if (error == 0) {
3262
					*inoffp += xfer;
3278
					*inoffp += xfer;
3263
					*outoffp += xfer;
3279
					*outoffp += xfer;
3264
					len -= xfer;
3280
					len -= xfer;
3281
printf("inoff=%ld outoff=%ld xfer=%ld len=%ld\n", *inoffp, *outoffp, xfer, len);
3265
					if (len < savlen)
3282
					if (len < savlen)
3266
						interrupted = sig_intr();
3283
						interrupted = sig_intr();
3267
				}
3284
				}
Lines 3286-3291 vn_generic_copy_file_range(struct vnode *invp, off_t * Link Here
3286
		}
3303
		}
3287
		/* Loop copying the data block. */
3304
		/* Loop copying the data block. */
3288
		while (copylen > 0 && error == 0 && !eof && interrupted == 0) {
3305
		while (copylen > 0 && error == 0 && !eof && interrupted == 0) {
3306
printf("in copyloop copylen=%ld xfer=%ld\n", copylen, xfer);
3289
			if (copylen < xfer)
3307
			if (copylen < xfer)
3290
				xfer = copylen;
3308
				xfer = copylen;
3291
			error = vn_lock(invp, LK_SHARED);
3309
			error = vn_lock(invp, LK_SHARED);

Return to bug 255523