[Midnightbsd-cvs] src [9393] trunk/sys/fs/msdosfs: Do a sync of the devvp vnode for the mount, which buffers, among other

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Sat Mar 4 16:27:20 EST 2017


Revision: 9393
          http://svnweb.midnightbsd.org/src/?rev=9393
Author:   laffer1
Date:     2017-03-04 16:27:20 -0500 (Sat, 04 Mar 2017)
Log Message:
-----------
Do a sync of the devvp vnode for the mount, which buffers, among other
things, contain FAT blocks.  This makes fsync(2) for msdosfs more correct
by syncing the metadata needed to read the synced data.

Modified Paths:
--------------
    trunk/sys/fs/msdosfs/msdosfs_denode.c
    trunk/sys/fs/msdosfs/msdosfs_vnops.c

Modified: trunk/sys/fs/msdosfs/msdosfs_denode.c
===================================================================
--- trunk/sys/fs/msdosfs/msdosfs_denode.c	2017-03-04 21:26:28 UTC (rev 9392)
+++ trunk/sys/fs/msdosfs/msdosfs_denode.c	2017-03-04 21:27:20 UTC (rev 9393)
@@ -294,16 +294,20 @@
 	struct denode *dep;
 	int waitfor;
 {
-	int error;
+	struct direntry dir;
+	struct timespec ts;
 	struct buf *bp;
 	struct direntry *dirp;
-	struct timespec ts;
+	int error;
 
-	if (DETOV(dep)->v_mount->mnt_flag & MNT_RDONLY)
+	if (DETOV(dep)->v_mount->mnt_flag & MNT_RDONLY) {
+		dep->de_flag &= ~(DE_UPDATE | DE_CREATE | DE_ACCESS |
+		    DE_MODIFIED);
 		return (0);
+	}
 	getnanotime(&ts);
 	DETIMES(dep, &ts, &ts, &ts);
-	if ((dep->de_flag & DE_MODIFIED) == 0)
+	if ((dep->de_flag & DE_MODIFIED) == 0 && waitfor == 0)
 		return (0);
 	dep->de_flag &= ~DE_MODIFIED;
 	if (dep->de_Attributes & ATTR_DIRECTORY)
@@ -313,13 +317,23 @@
 	error = readde(dep, &bp, &dirp);
 	if (error)
 		return (error);
-	DE_EXTERNALIZE(dirp, dep);
+	DE_EXTERNALIZE(&dir, dep);
+	if (bcmp(dirp, &dir, sizeof(dir)) == 0) {
+		if (waitfor == 0 || (bp->b_flags & B_DELWRI) == 0) {
+			brelse(bp);
+			return (0);
+		}
+	} else
+		*dirp = dir;
+	if ((DETOV(dep)->v_mount->mnt_flag & MNT_NOCLUSTERW) == 0)
+		bp->b_flags |= B_CLUSTEROK;
 	if (waitfor)
-		return (bwrite(bp));
-	else {
+		error = bwrite(bp);
+	else if (vm_page_count_severe() || buf_dirty_count_severe())
+		bawrite(bp);
+	else
 		bdwrite(bp);
-		return (0);
-	}
+	return (error);
 }
 
 /*

Modified: trunk/sys/fs/msdosfs/msdosfs_vnops.c
===================================================================
--- trunk/sys/fs/msdosfs/msdosfs_vnops.c	2017-03-04 21:26:28 UTC (rev 9392)
+++ trunk/sys/fs/msdosfs/msdosfs_vnops.c	2017-03-04 21:27:20 UTC (rev 9393)
@@ -850,9 +850,6 @@
 
 /*
  * Flush the blocks of a file to disk.
- *
- * This function is worthless for vnodes that represent directories. Maybe we
- * could just do a sync if they try an fsync on a directory file.
  */
 static int
 msdosfs_fsync(ap)
@@ -863,9 +860,35 @@
 		struct thread *a_td;
 	} */ *ap;
 {
+	struct vnode *devvp;
+	int allerror, error;
 
 	vop_stdfsync(ap);
-	return (deupdat(VTODE(ap->a_vp), ap->a_waitfor == MNT_WAIT));
+
+	/*
+	* If the syncing request comes from fsync(2), sync the entire
+	* FAT and any other metadata that happens to be on devvp.  We
+	* need this mainly for the FAT.  We write the FAT sloppily, and
+	* syncing it all now is the best we can easily do to get all
+	* directory entries associated with the file (not just the file)
+	* fully synced.  The other metadata includes critical metadata
+	* for all directory entries, but only in the MNT_ASYNC case.  We
+	* will soon sync all metadata in the file's directory entry.
+	* Non-critical metadata for associated directory entries only
+	* gets synced accidentally, as in most file systems.
+	*/
+	if (ap->a_waitfor == MNT_WAIT) {
+		devvp = VTODE(ap->a_vp)->de_pmp->pm_devvp;
+		vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
+		allerror = VOP_FSYNC(devvp, MNT_WAIT, ap->a_td);
+		VOP_UNLOCK(devvp, 0);
+	} else
+		allerror = 0;
+
+	error = deupdat(VTODE(ap->a_vp), ap->a_waitfor == MNT_WAIT);
+	if (allerror == 0)
+		allerror = error;
+	return (allerror);
 }
 
 static int



More information about the Midnightbsd-cvs mailing list