svn commit: r250694 - stable/9/sys/fs/msdosfs

Konstantin Belousov kib at FreeBSD.org
Thu May 16 06:19:30 UTC 2013


Author: kib
Date: Thu May 16 06:19:29 2013
New Revision: 250694
URL: http://svnweb.freebsd.org/changeset/base/250694

Log:
  MFC r250193:
  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:
  stable/9/sys/fs/msdosfs/msdosfs_denode.c
  stable/9/sys/fs/msdosfs/msdosfs_vnops.c
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/fs/   (props changed)

Modified: stable/9/sys/fs/msdosfs/msdosfs_denode.c
==============================================================================
--- stable/9/sys/fs/msdosfs/msdosfs_denode.c	Thu May 16 05:16:56 2013	(r250693)
+++ stable/9/sys/fs/msdosfs/msdosfs_denode.c	Thu May 16 06:19:29 2013	(r250694)
@@ -294,16 +294,20 @@ deupdat(dep, waitfor)
 	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 @@ deupdat(dep, waitfor)
 	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: stable/9/sys/fs/msdosfs/msdosfs_vnops.c
==============================================================================
--- stable/9/sys/fs/msdosfs/msdosfs_vnops.c	Thu May 16 05:16:56 2013	(r250693)
+++ stable/9/sys/fs/msdosfs/msdosfs_vnops.c	Thu May 16 06:19:29 2013	(r250694)
@@ -850,9 +850,6 @@ errexit:
 
 /*
  * 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 @@ msdosfs_fsync(ap)
 		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 svn-src-all mailing list