From alex@alexwang.com Wed Apr 7 11:31:52 2004 Return-Path: Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 1504816A4CE for ; Wed, 7 Apr 2004 11:31:52 -0700 (PDT) Received: from alexwang.com (alexwang.com [61.62.231.187]) by mx1.FreeBSD.org (Postfix) with ESMTP id 4CC4B43D49 for ; Wed, 7 Apr 2004 11:31:51 -0700 (PDT) (envelope-from alex@alexwang.com) Received: from alexwang.com (localhost.alexwang.com [127.0.0.1]) by alexwang.com (8.12.10/8.12.10) with ESMTP id i37IVYA7001226 for ; Thu, 8 Apr 2004 02:31:34 +0800 (CST) Received: (from root@localhost) by alexwang.com (8.12.10/8.12.10/Submit) id i37IVY3K001225; Thu, 8 Apr 2004 02:31:34 +0800 (CST) (envelope-from alex) Message-Id: <200404071831.i37IVY3K001225@alexwang.com> Date: Thu, 8 Apr 2004 02:31:34 +0800 (CST) From: Alex Wang Reply-To: Alex Wang To: FreeBSD-gnats-submit@freebsd.org Cc: Subject: Can't use sendfile(2) to download files in UDF DVD X-Send-Pr-Version: 3.113 X-GNATS-Notify: >Number: 65300 >Category: kern >Synopsis: [udf] [patch] Can't use sendfile(2) to download files in UDF DVD >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: closed >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Apr 07 11:40:15 PDT 2004 >Closed-Date: Wed Feb 28 12:01:25 GMT 2007 >Last-Modified: Wed Feb 28 12:01:25 GMT 2007 >Originator: Alex Wang >Release: FreeBSD 5.2-RELEASE i386 >Organization: >Environment: System: FreeBSD alexwang.com 5.2-RELEASE FreeBSD 5.2-RELEASE #0: Tue Jan 13 23:04:18 CST 2004 alex@alexwang.com:/usr/src/sys/i386/compile/ALEX i386 >Description: Files in UDF filesystem can't be downlaod through ftp (sendfile(2)). It seems the udf_read() can't map the right vm page. >How-To-Repeat: Just download a file in UDF DVD throught FTP. The file content would be very strange. >Fix: >Release-Note: >Audit-Trail: From: "Alex Wang" To: , "ALEX" Cc: Subject: Re: kern/65300: Can't use sendfile(2) to download files in UDF DVD Date: Fri, 9 Apr 2004 03:06:33 +0800 This is a multi-part message in MIME format. ------=_NextPart_000_002E_01C41DDF.A9B7BD00 Content-Type: text/plain; charset="big5" Content-Transfer-Encoding: quoted-printable I guess the reason is the sendfile(2) get page by the file vp and offset = but the udf_read gives bread() device vp and sector. So the bread can't = get the same page with sendfile(). We should give bread file vp and offset. Then transfer into device vp = and logical block in udf_strategy.=20 ------=_NextPart_000_002E_01C41DDF.A9B7BD00 Content-Type: text/html; charset="big5" Content-Transfer-Encoding: quoted-printable
I guess the reason is the sendfile(2) = get page by=20 the file vp and offset but the udf_read gives bread() device vp and = sector. So=20 the bread can't get the same page with sendfile().
We should give bread file vp and = offset. Then=20 transfer into device vp and logical block in udf_strategy.=20
------=_NextPart_000_002E_01C41DDF.A9B7BD00-- From: Pav Lucistnik To: bug-followup@FreeBSD.org, alex@alexwang.com Cc: Subject: Re: kern/65300: [udf] Can't use sendfile(2) to download files in UDF DVD Date: Tue, 09 Jan 2007 02:44:45 +0100 Please try this patch, it fixes the issue for me. Tested on 6-STABLE, should apply and work in -CURRENT too. Index: udf_vnops.c =================================================================== RCS file: /home/ncvs/src/sys/fs/udf/udf_vnops.c,v retrieving revision 1.58.2.2 diff -a -u -r1.58.2.2 udf_vnops.c --- udf_vnops.c 30 Dec 2006 15:42:11 -0000 1.58.2.2 +++ udf_vnops.c 9 Jan 2007 01:22:12 -0000 @@ -339,38 +339,60 @@ } } +#define lblkno(udfmp, loc) ((loc) >> (udfmp)->bshift) +#define blkoff(udfmp, loc) ((loc) & (udfmp)->bmask) +#define lblktosize(imp, blk) ((blk) << (udfmp)->bshift) + static int -udf_read(struct vop_read_args *a) +udf_read(struct vop_read_args *ap) { - struct vnode *vp = a->a_vp; - struct uio *uio = a->a_uio; + struct vnode *vp = ap->a_vp; + struct uio *uio = ap->a_uio; struct udf_node *node = VTON(vp); + struct udf_mnt *udfmp; struct buf *bp; - uint8_t *data; - off_t fsize, offset; + daddr_t lbn, rablock; + off_t diff, fsize; int error = 0; - int size; + long size, n, on; + if (uio->uio_resid == 0) + return (0); if (uio->uio_offset < 0) return (EINVAL); - fsize = le64toh(node->fentry->inf_len); - - while (uio->uio_offset < fsize && uio->uio_resid > 0) { - offset = uio->uio_offset; - if (uio->uio_resid + offset <= fsize) - size = uio->uio_resid; - else - size = fsize - offset; - error = udf_readatoffset(node, &size, offset, &bp, &data); - if (error == 0) - error = uiomove(data, size, uio); - if (bp != NULL) + udfmp = node->udfmp; + do { + lbn = lblkno(udfmp, uio->uio_offset); + on = blkoff(udfmp, uio->uio_offset); + n = min((u_int)(udfmp->bsize - on), + uio->uio_resid); + diff = fsize - uio->uio_offset; + if (diff <= 0) + return (0); + if (diff < n) + n = diff; + size = udfmp->bsize; + rablock = lbn + 1; + if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) { + if (lblktosize(udfmp, rablock) < fsize) { + error = cluster_read(vp, fsize, lbn, size, NOCRED, + uio->uio_resid, (ap->a_ioflag >> 16), &bp); + } else { + error = bread(vp, lbn, size, NOCRED, &bp); + } + } else { + error = bread(vp, lbn, size, NOCRED, &bp); + } + n = min(n, size - bp->b_resid); + if (error) { brelse(bp); - if (error) - break; - }; + return (error); + } + error = uiomove(bp->b_data + on, (int)n, uio); + brelse(bp); + } while (error == 0 && uio->uio_resid > 0 && n != 0); return (error); } @@ -776,23 +798,29 @@ struct vnode *vp; struct udf_node *node; int maxsize; + daddr_t sector; struct bufobj *bo; + int multiplier; bp = a->a_bp; vp = a->a_vp; node = VTON(vp); - /* cd9660 has this test reversed, but it seems more logical this way */ - if (bp->b_blkno != bp->b_lblkno) { + if (bp->b_blkno == bp->b_lblkno) { /* * Files that are embedded in the fentry don't translate well * to a block number. Reject. */ if (udf_bmap_internal(node, bp->b_lblkno * node->udfmp->bsize, - &bp->b_lblkno, &maxsize)) { + §or, &maxsize)) { clrbuf(bp); bp->b_blkno = -1; } + + /* bmap gives sector numbers, bio works with device blocks */ + multiplier = node->udfmp->bsize / DEV_BSIZE; + bp->b_blkno = sector * multiplier; + } if ((long)bp->b_blkno == -1) { bufdone(bp); -- Pav Lucistnik It's ten o'clock; do you know where your processes are? State-Changed-From-To: open->feedback State-Changed-By: remko State-Changed-When: Tue Jan 9 06:19:42 UTC 2007 State-Changed-Why: Pav submitted a patch, can you please try this and let us know the results? http://www.freebsd.org/cgi/query-pr.cgi?pr=65300 State-Changed-From-To: feedback->closed State-Changed-By: remko State-Changed-When: Wed Feb 28 12:01:24 UTC 2007 State-Changed-Why: No feedback, no game, close the ticket. http://www.freebsd.org/cgi/query-pr.cgi?pr=65300 >Unformatted: