summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>2007-10-19 12:23:25 +0000
committerbde <bde@FreeBSD.org>2007-10-19 12:23:25 +0000
commitc590272b42e93312c35e2c65311528e435564f7c (patch)
treee84a4ea00d6316f70a28395022018de01e8f9ddc
parent6447f9aa646b2b502fd5d41a1f2c0de50090b3dd (diff)
downloadFreeBSD-src-c590272b42e93312c35e2c65311528e435564f7c.zip
FreeBSD-src-c590272b42e93312c35e2c65311528e435564f7c.tar.gz
Implement the async (really, delayed-write) mount option for msdosfs.
This is much simpler than for ffs since there are many fewer places where we need to choose between a delayed write and a sync write -- just 5 in msdosfs and more than 30 in ffs. This is more complete and correct than in ffs. Several places in ffs are are still missing the choice. ffs_update() has a layering violation that breaks callers which want to force a sync update (mainly fsync(2) and O_SYNC write(2)). However, fsync(2) and O_SYNC write(2) are still more broken than in ffs, since they are broken for default (non-sync non-async) mounts too. Both fail to sync the FAT in all cases, and both fail to sync the directory entry in some cases after losing a race. Async everything is probably safer than the half-baked sync of metadata given by default mounts.
-rw-r--r--sys/fs/msdosfs/msdosfs_denode.c4
-rw-r--r--sys/fs/msdosfs/msdosfs_lookup.c12
-rw-r--r--sys/fs/msdosfs/msdosfs_vfsops.c2
-rw-r--r--sys/fs/msdosfs/msdosfs_vnops.c10
4 files changed, 18 insertions, 10 deletions
diff --git a/sys/fs/msdosfs/msdosfs_denode.c b/sys/fs/msdosfs/msdosfs_denode.c
index 37f1433..e3b962a 100644
--- a/sys/fs/msdosfs/msdosfs_denode.c
+++ b/sys/fs/msdosfs/msdosfs_denode.c
@@ -429,7 +429,7 @@ detrunc(dep, length, flags, cred, td)
if (allerror)
printf("detrunc(): vtruncbuf error %d\n", allerror);
#endif
- error = deupdat(dep, 1);
+ error = deupdat(dep, !(DETOV(dep)->v_mount->mnt_flag & MNT_ASYNC));
if (error != 0 && allerror == 0)
allerror = error;
#ifdef MSDOSFS_DEBUG
@@ -508,7 +508,7 @@ deextend(dep, length, cred)
}
dep->de_FileSize = length;
dep->de_flag |= DE_UPDATE | DE_MODIFIED;
- return (deupdat(dep, 1));
+ return (deupdat(dep, !(DETOV(dep)->v_mount->mnt_flag & MNT_ASYNC)));
}
/*
diff --git a/sys/fs/msdosfs/msdosfs_lookup.c b/sys/fs/msdosfs/msdosfs_lookup.c
index 9ebae3e..1c9a67d 100644
--- a/sys/fs/msdosfs/msdosfs_lookup.c
+++ b/sys/fs/msdosfs/msdosfs_lookup.c
@@ -625,7 +625,9 @@ createde(dep, ddep, depp, cnp)
while (--ddep->de_fndcnt >= 0) {
if (!(ddep->de_fndoffset & pmp->pm_crbomask)) {
- if ((error = bwrite(bp)) != 0)
+ if (DETOV(ddep)->v_mount->mnt_flag & MNT_ASYNC)
+ bdwrite(bp);
+ else if ((error = bwrite(bp)) != 0)
return error;
ddep->de_fndoffset -= sizeof(struct direntry);
@@ -653,7 +655,9 @@ createde(dep, ddep, depp, cnp)
}
}
- if ((error = bwrite(bp)) != 0)
+ if (DETOV(ddep)->v_mount->mnt_flag & MNT_ASYNC)
+ bdwrite(bp);
+ else if ((error = bwrite(bp)) != 0)
return error;
/*
@@ -951,7 +955,9 @@ removede(pdep, dep)
|| ep->deAttributes != ATTR_WIN95)
break;
}
- if ((error = bwrite(bp)) != 0)
+ if (DETOV(pdep)->v_mount->mnt_flag & MNT_ASYNC)
+ bdwrite(bp);
+ else if ((error = bwrite(bp)) != 0)
return error;
} while (!(pmp->pm_flags & MSDOSFSMNT_NOWIN95)
&& !(offset & pmp->pm_crbomask)
diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c
index 8b65dd8..b456667 100644
--- a/sys/fs/msdosfs/msdosfs_vfsops.c
+++ b/sys/fs/msdosfs/msdosfs_vfsops.c
@@ -76,7 +76,7 @@
/* Mount options that we support. */
static const char *msdosfs_opts[] = {
- "noatime", "noclusterr", "noclusterw",
+ "async", "noatime", "noclusterr", "noclusterw",
"export", "force", "from", "sync",
"cs_dos", "cs_local", "cs_win", "dirmask",
"gid", "kiconv", "large", "longname",
diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c
index 1a4c970..96f63ff 100644
--- a/sys/fs/msdosfs/msdosfs_vnops.c
+++ b/sys/fs/msdosfs/msdosfs_vnops.c
@@ -1265,8 +1265,9 @@ abortit:
putushort(dotdotp->deStartCluster, dp->de_StartCluster);
if (FAT32(pmp))
putushort(dotdotp->deHighClust, dp->de_StartCluster >> 16);
- error = bwrite(bp);
- if (error) {
+ if (fvp->v_mount->mnt_flag & MNT_ASYNC)
+ bdwrite(bp);
+ else if ((error = bwrite(bp)) != 0) {
/* XXX should downgrade to ro here, fs is corrupt */
VOP_UNLOCK(fvp, 0, td);
goto bad;
@@ -1390,8 +1391,9 @@ msdosfs_mkdir(ap)
putushort(denp[1].deHighClust, pdep->de_StartCluster >> 16);
}
- error = bwrite(bp);
- if (error)
+ if (ap->a_dvp->v_mount->mnt_flag & MNT_ASYNC)
+ bdwrite(bp);
+ else if ((error = bwrite(bp)) != 0)
goto bad;
/*
OpenPOWER on IntegriCloud