aboutsummaryrefslogtreecommitdiff
path: root/sys/fs/ntfs/ntfs_vnops.c
diff options
context:
space:
mode:
authorSemen Ustimenko <semenu@FreeBSD.org>2002-07-31 00:42:57 +0000
committerSemen Ustimenko <semenu@FreeBSD.org>2002-07-31 00:42:57 +0000
commitb0c1faefddc8e9564347eed879ea0ae17ff4a960 (patch)
tree027931a408523776d8a87f2cd76db04b50d3c6df /sys/fs/ntfs/ntfs_vnops.c
parent4024496496955e07a83f01016b0cfb05b4b2432e (diff)
downloadsrc-b0c1faefddc8e9564347eed879ea0ae17ff4a960.tar.gz
src-b0c1faefddc8e9564347eed879ea0ae17ff4a960.zip
Fix a problem with sendfile() syscall by always doing I/O via bread() in
ntfs_read(). This guarantee that requested cache pages will be valid if UIO_NOCOPY specifed. PR: bin/34072, bin/36189 MFC after: 1 week
Notes
Notes: svn path=/head/; revision=101002
Diffstat (limited to 'sys/fs/ntfs/ntfs_vnops.c')
-rw-r--r--sys/fs/ntfs/ntfs_vnops.c41
1 files changed, 28 insertions, 13 deletions
diff --git a/sys/fs/ntfs/ntfs_vnops.c b/sys/fs/ntfs/ntfs_vnops.c
index 52e24c693cec..dbb559383d9f 100644
--- a/sys/fs/ntfs/ntfs_vnops.c
+++ b/sys/fs/ntfs/ntfs_vnops.c
@@ -101,7 +101,9 @@ ntfs_read(ap)
register struct ntnode *ip = FTONT(fp);
struct uio *uio = ap->a_uio;
struct ntfsmount *ntmp = ip->i_mp;
- u_int64_t toread;
+ struct buf *bp;
+ daddr_t cn;
+ int resid, off, toread;
int error;
dprintf(("ntfs_read: ino: %d, off: %d resid: %d, segflg: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid,uio->uio_segflg));
@@ -110,23 +112,36 @@ ntfs_read(ap)
/* don't allow reading after end of file */
if (uio->uio_offset > fp->f_size)
- toread = 0;
- else
- toread = min( uio->uio_resid, fp->f_size - uio->uio_offset );
+ return (0);
- dprintf((", toread: %d\n",(u_int32_t)toread));
+ resid = min(uio->uio_resid, fp->f_size - uio->uio_offset);
- if (toread == 0)
- return (0);
+ dprintf((", resid: %d\n", resid));
- error = ntfs_readattr(ntmp, ip, fp->f_attrtype,
- fp->f_attrname, uio->uio_offset, toread, NULL, uio);
- if (error) {
- printf("ntfs_read: ntfs_readattr failed: %d\n",error);
- return (error);
+ error = 0;
+ while (resid) {
+ cn = ntfs_btocn(uio->uio_offset);
+ off = ntfs_btocnoff(uio->uio_offset);
+
+ toread = min(off + resid, ntfs_cntob(1));
+
+ error = bread(vp, cn, ntfs_cntob(1), NOCRED, &bp);
+ if (error) {
+ brelse(bp);
+ break;
+ }
+
+ error = uiomove(bp->b_data + off, toread - off, uio);
+ if(error) {
+ brelse(bp);
+ break;
+ }
+ brelse(bp);
+
+ resid -= toread - off;
}
- return (0);
+ return (error);
}
static int