From cb65c1ee29fe88093a40f4b77eb9229d11eac0cd Mon Sep 17 00:00:00 2001 From: Bruce Evans Date: Fri, 19 Oct 2007 12:23:25 +0000 Subject: 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. --- sys/fs/msdosfs/msdosfs_denode.c | 4 ++-- sys/fs/msdosfs/msdosfs_lookup.c | 12 +++++++++--- sys/fs/msdosfs/msdosfs_vfsops.c | 2 +- sys/fs/msdosfs/msdosfs_vnops.c | 10 ++++++---- 4 files changed, 18 insertions(+), 10 deletions(-) (limited to 'sys/fs/msdosfs') diff --git a/sys/fs/msdosfs/msdosfs_denode.c b/sys/fs/msdosfs/msdosfs_denode.c index 37f1433ff298..e3b962a5f5fb 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 9ebae3e48327..1c9a67d1d19b 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 8b65dd8b1ec0..b45666740519 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 1a4c970aeeaa..96f63ff5fc33 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; /* -- cgit v1.3