summaryrefslogtreecommitdiff
path: root/sys/msdosfs/msdosfs_vnops.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/msdosfs/msdosfs_vnops.c')
-rw-r--r--sys/msdosfs/msdosfs_vnops.c190
1 files changed, 83 insertions, 107 deletions
diff --git a/sys/msdosfs/msdosfs_vnops.c b/sys/msdosfs/msdosfs_vnops.c
index 7f1ab384295..1e364039937 100644
--- a/sys/msdosfs/msdosfs_vnops.c
+++ b/sys/msdosfs/msdosfs_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: msdosfs_vnops.c,v 1.28 2001/11/06 19:53:20 miod Exp $ */
+/* $OpenBSD: msdosfs_vnops.c,v 1.29 2001/11/27 05:27:12 art Exp $ */
/* $NetBSD: msdosfs_vnops.c,v 1.63 1997/10/17 11:24:19 ws Exp $ */
/*-
@@ -413,11 +413,11 @@ msdosfs_read(v)
int error = 0;
int diff;
int blsize;
- int isadir;
long n;
long on;
daddr_t lbn;
- daddr_t rablock;
+ void *win;
+ vsize_t bytelen;
struct buf *bp;
struct vnode *vp = ap->a_vp;
struct denode *dep = VTODE(vp);
@@ -432,42 +432,45 @@ msdosfs_read(v)
if (uio->uio_offset < 0)
return (EINVAL);
- isadir = dep->de_Attributes & ATTR_DIRECTORY;
+ if (vp->v_type == VREG) {
+ while (uio->uio_resid > 0) {
+ bytelen = MIN(dep->de_FileSize - uio->uio_offset,
+ uio->uio_resid);
+
+ if (bytelen == 0)
+ break;
+ win = ubc_alloc(&vp->v_uvm.u_obj, uio->uio_offset,
+ &bytelen, UBC_READ);
+ error = uiomove(win, bytelen, uio);
+ ubc_release(win, 0);
+ if (error)
+ break;
+ }
+ dep->de_flag |= DE_ACCESS;
+ goto out;
+ }
+
+ /* this loop is only for directories now */
do {
lbn = de_cluster(pmp, uio->uio_offset);
on = uio->uio_offset & pmp->pm_crbomask;
- n = min((u_long) (pmp->pm_bpcluster - on), uio->uio_resid);
+ n = MIN((pmp->pm_bpcluster - on), uio->uio_resid);
diff = dep->de_FileSize - uio->uio_offset;
if (diff <= 0)
return (0);
if (diff < n)
n = diff;
/* convert cluster # to block # if a directory */
- if (isadir) {
- error = pcbmap(dep, lbn, &lbn, 0, &blsize);
- if (error)
- return (error);
- }
+ error = pcbmap(dep, lbn, &lbn, 0, &blsize);
+ if (error)
+ return (error);
/*
* If we are operating on a directory file then be sure to
* do i/o with the vnode for the filesystem instead of the
* vnode for the directory.
*/
- if (isadir) {
- error = bread(pmp->pm_devvp, lbn, blsize, NOCRED, &bp);
- } else {
- rablock = lbn + 1;
- if (dep->de_lastr + 1 == lbn &&
- de_cn2off(pmp, rablock) < dep->de_FileSize)
- error = breada(vp, de_cn2bn(pmp, lbn),
- pmp->pm_bpcluster, de_cn2bn(pmp, rablock),
- pmp->pm_bpcluster, NOCRED, &bp);
- else
- error = bread(vp, de_cn2bn(pmp, lbn),
- pmp->pm_bpcluster, NOCRED, &bp);
- dep->de_lastr = lbn;
- }
- n = min(n, pmp->pm_bpcluster - bp->b_resid);
+ error = bread(pmp->pm_devvp, lbn, blsize, NOCRED, &bp);
+ n = MIN(n, pmp->pm_bpcluster - bp->b_resid);
if (error) {
brelse(bp);
return (error);
@@ -475,8 +478,10 @@ msdosfs_read(v)
error = uiomove(bp->b_data + on, (int) n, uio);
brelse(bp);
} while (error == 0 && uio->uio_resid > 0 && n != 0);
- if (!isadir && !(vp->v_mount->mnt_flag & MNT_NOATIME))
- dep->de_flag |= DE_ACCESS;
+
+out:
+ if ((ap->a_ioflag & IO_SYNC) == IO_SYNC)
+ error = deupdat(dep, 1);
return (error);
}
@@ -493,19 +498,19 @@ msdosfs_write(v)
int a_ioflag;
struct ucred *a_cred;
} */ *ap = v;
- int n;
- int croffset;
int resid;
u_long osize;
int error = 0;
u_long count;
- daddr_t bn, lastcn;
- struct buf *bp;
+ daddr_t lastcn;
int ioflag = ap->a_ioflag;
+ void *win;
+ vsize_t bytelen;
+ off_t oldoff;
+ boolean_t rv;
struct uio *uio = ap->a_uio;
struct proc *p = uio->uio_procp;
struct vnode *vp = ap->a_vp;
- struct vnode *thisvp;
struct denode *dep = VTODE(vp);
struct msdosfsmount *pmp = dep->de_pmp;
struct ucred *cred = ap->a_cred;
@@ -521,7 +526,6 @@ msdosfs_write(v)
case VREG:
if (ioflag & IO_APPEND)
uio->uio_offset = dep->de_FileSize;
- thisvp = vp;
break;
case VDIR:
return EISDIR;
@@ -576,84 +580,52 @@ msdosfs_write(v)
} else
lastcn = de_clcount(pmp, osize) - 1;
+ if (dep->de_FileSize < uio->uio_offset + resid) {
+ dep->de_FileSize = uio->uio_offset + resid;
+ uvm_vnp_setsize(vp, dep->de_FileSize);
+ }
+
do {
- if (de_cluster(pmp, uio->uio_offset) > lastcn) {
+ oldoff = uio->uio_offset;
+ if (de_cluster(pmp, oldoff) > lastcn) {
error = ENOSPC;
break;
}
-
- bn = de_blk(pmp, uio->uio_offset);
- if ((uio->uio_offset & pmp->pm_crbomask) == 0
- && (de_blk(pmp, uio->uio_offset + uio->uio_resid) > de_blk(pmp, uio->uio_offset)
- || uio->uio_offset + uio->uio_resid >= dep->de_FileSize)) {
- /*
- * If either the whole cluster gets written,
- * or we write the cluster from its start beyond EOF,
- * then no need to read data from disk.
- */
- bp = getblk(thisvp, bn, pmp->pm_bpcluster, 0, 0);
- clrbuf(bp);
- /*
- * Do the bmap now, since pcbmap needs buffers
- * for the fat table. (see msdosfs_strategy)
- */
- if (bp->b_blkno == bp->b_lblkno) {
- error = pcbmap(dep,
- de_bn2cn(pmp, bp->b_lblkno),
- &bp->b_blkno, 0, 0);
- if (error)
- bp->b_blkno = -1;
- }
- if (bp->b_blkno == -1) {
- brelse(bp);
- if (!error)
- error = EIO; /* XXX */
- break;
- }
- } else {
- /*
- * The block we need to write into exists, so read it in.
- */
- error = bread(thisvp, bn, pmp->pm_bpcluster,
- NOCRED, &bp);
- if (error) {
- brelse(bp);
- break;
- }
- }
-
- croffset = uio->uio_offset & pmp->pm_crbomask;
- n = min(uio->uio_resid, pmp->pm_bpcluster - croffset);
- if (uio->uio_offset + n > dep->de_FileSize) {
- dep->de_FileSize = uio->uio_offset + n;
- uvm_vnp_setsize(vp, dep->de_FileSize);
- }
- uvm_vnp_uncache(vp);
- /*
- * Should these vnode_pager_* functions be done on dir
- * files?
- */
+ bytelen = MIN(dep->de_FileSize - oldoff, uio->uio_resid);
/*
- * Copy the data from user space into the buf header.
+ * XXXUBC if file is mapped and this is the last block,
+ * process one page at a time.
*/
- error = uiomove(bp->b_data + croffset, n, uio);
+ if (bytelen == 0)
+ break;
+ win = ubc_alloc(&vp->v_uvm.u_obj, oldoff, &bytelen, UBC_READ);
+ error = uiomove(win, bytelen, uio);
+ ubc_release(win, 0);
+ if (error) {
+ break;
+ }
/*
- * If they want this synchronous then write it and wait for
- * it. Otherwise, if on a cluster boundary write it
- * asynchronously so we can move on to the next block
- * without delay. Otherwise do a delayed write because we
- * may want to write somemore into the block later.
+ * flush what we just wrote if necessary.
+ * XXXUBC simplistic async flushing.
*/
- if (ioflag & IO_SYNC)
- (void) bwrite(bp);
- else if (n + croffset == pmp->pm_bpcluster)
- bawrite(bp);
- else
- bdwrite(bp);
- dep->de_flag |= DE_UPDATE;
+ if (ioflag & IO_SYNC) {
+
+ simple_lock(&vp->v_uvm.u_obj.vmobjlock);
+ rv = vp->v_uvm.u_obj.pgops->pgo_flush(
+ &vp->v_uvm.u_obj, oldoff,
+ oldoff + bytelen, PGO_CLEANIT|PGO_SYNCIO);
+ simple_unlock(&vp->v_uvm.u_obj.vmobjlock);
+ } else if (oldoff >> 16 != uio->uio_offset >> 16) {
+ simple_lock(&vp->v_uvm.u_obj.vmobjlock);
+ rv = vp->v_uvm.u_obj.pgops->pgo_flush(
+ &vp->v_uvm.u_obj, (oldoff >> 16) << 16,
+ (uio->uio_offset >> 16) << 16, PGO_CLEANIT);
+ simple_unlock(&vp->v_uvm.u_obj.vmobjlock);
+ }
} while (error == 0 && uio->uio_resid > 0);
+ dep->de_flag |= DE_UPDATE;
/*
* If the write failed and they want us to, truncate the file back
@@ -666,7 +638,8 @@ errexit:
uio->uio_offset -= resid - uio->uio_resid;
uio->uio_resid = resid;
} else {
- detrunc(dep, dep->de_FileSize, ioflag & IO_SYNC, NOCRED, NULL);
+ detrunc(dep, dep->de_FileSize, ioflag & IO_SYNC, NOCRED,
+ NULL);
if (uio->uio_resid != resid)
error = 0;
}
@@ -1506,11 +1479,11 @@ msdosfs_readdir(v)
while (uio->uio_resid > 0) {
lbn = de_cluster(pmp, offset - bias);
on = (offset - bias) & pmp->pm_crbomask;
- n = min(pmp->pm_bpcluster - on, uio->uio_resid);
+ n = MIN(pmp->pm_bpcluster - on, uio->uio_resid);
diff = dep->de_FileSize - (offset - bias);
if (diff <= 0)
break;
- n = min(n, diff);
+ n = MIN(n, diff);
if ((error = pcbmap(dep, lbn, &bn, &cn, &blsize)) != 0)
break;
error = bread(pmp->pm_devvp, bn, blsize, NOCRED, &bp);
@@ -1518,7 +1491,7 @@ msdosfs_readdir(v)
brelse(bp);
return (error);
}
- n = min(n, blsize - bp->b_resid);
+ n = MIN(n, blsize - bp->b_resid);
/*
* Convert from dos directory entries to fs-independent
@@ -1779,12 +1752,12 @@ msdosfs_strategy(v)
biodone(bp);
return (error);
}
-#ifdef DIAGNOSTIC
-#endif
+
/*
* Read/write the block from/to the disk that contains the desired
* file block.
*/
+
vp = dep->de_devvp;
bp->b_dev = vp->v_rdev;
VOCALL(vp->v_op, VOFFSET(vop_strategy), ap);
@@ -1902,7 +1875,10 @@ struct vnodeopv_entry_desc msdosfs_vnodeop_entries[] = {
{ &vop_advlock_desc, msdosfs_advlock }, /* advlock */
{ &vop_reallocblks_desc, msdosfs_reallocblks }, /* reallocblks */
{ &vop_bwrite_desc, vop_generic_bwrite }, /* bwrite */
- { (struct vnodeop_desc *)NULL, (int (*) __P((void *)))NULL }
+ { &vop_getpages_desc, genfs_getpages },
+ { &vop_putpages_desc, genfs_putpages },
+ { &vop_size_desc, genfs_size },
+ { NULL, NULL }
};
struct vnodeopv_desc msdosfs_vnodeop_opv_desc =
{ &msdosfs_vnodeop_p, msdosfs_vnodeop_entries };