kern/62762: Fsync for msdos fs does not sync entries

Amit Khivesara khivi at psyche.nj.us.utstar.com
Thu Feb 12 16:10:14 PST 2004


>Number:         62762
>Category:       kern
>Synopsis:       Fsync for msdos fs does not sync entries
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Feb 12 16:10:13 PST 2004
>Closed-Date:
>Last-Modified:
>Originator:     Amit Khivesara
>Release:        FreeBSD 4.9-RELEASE i386
>Organization:
>Environment:
System: FreeBSD mobo11 4.9-XOS-kernel-4.9-dev Build 44281 2004/02/12 16:34:09, khivi at psyche 2004/02/12 18:53:46 FreeBSD  root at psyche.nj.us.utstar.com:/usr/home/khivi/p4/mobo-4.9/kernel/build/kernel/DISKLESS  i386
>Description:
	Fsync on a file should sync all the data and meta-data blocks
	for the file. For the msdos fs, the fat enteries do not get synced.
	
>How-To-Repeat:
	Do multiple file writes on a file  and fsync the file.
	Reboot really fast (pull power plug or reboot -q -n ).  Basically you
	do not want the syncher to come in and sync the dirty blocks.
	On power up the files will contain a partial file or a bad file.
>Fix:

diff -ur msdosfs.old/fat.h msdosfs.new/fat.h
--- msdosfs.old/fat.h	Thu Feb 12 18:39:32 2004
+++ msdosfs.new/fat.h	Thu Feb 12 18:36:13 2004
@@ -104,5 +104,6 @@
 int freeclusterchain __P((struct msdosfsmount *pmp, u_long startchain));
 int extendfile __P((struct denode *dep, u_long count, struct buf **bpp, u_long *ncp, int flags));
 void fc_purge __P((struct denode *dep, u_int frcn));
+void fat_sync __P((struct vnode * , struct denode *dep));
 
 #endif	/* _KERNEL */
diff -ur msdosfs.old/msdosfs_fat.c msdosfs.new/msdosfs_fat.c
--- msdosfs.old/msdosfs_fat.c	Thu Feb 12 18:39:32 2004
+++ msdosfs.new/msdosfs_fat.c	Thu Feb 12 18:49:38 2004
@@ -322,6 +322,80 @@
 	}
 }
 
+
+/*
+ * Sync the fat cache in denode dep of all entries relating to file
+ */
+void
+fat_sync(vnode,dep)
+	struct vnode *vnode;
+	struct denode *dep;
+{
+    u_long cn;
+    u_long prevcn;
+
+    u_long byteoffset;
+    u_long bsize;
+    u_long bo;
+    u_long bn;
+	u_long bp_bn = -1;
+	int error;
+    struct buf *bp = NULL;
+    struct msdosfsmount *pmp = dep->de_pmp;
+
+    u_int pm_flags=pmp->pm_flags;
+    pmp->pm_flags |= MSDOSFSMNT_WAITONFAT;
+
+     cn=dep->de_StartCluster;
+     while (1){
+		/*
+		 * Stop with all reserved clusters, not just with EOF.
+		 */
+		if ((cn | ~pmp->pm_fatmask) >= CLUST_RSRVD)
+			goto hiteof;
+		byteoffset = FATOFS(pmp, cn);
+		fatblock(pmp, byteoffset, &bn, &bsize, &bo);
+		if (bn != bp_bn) {
+			if (bp) {
+                                updatefats(pmp, bp, bp_bn);
+                        }
+			error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
+			if (error) {
+				brelse(bp);
+				goto func_ret;
+			}
+			bp_bn = bn;
+		}
+
+		prevcn = cn;
+		if (FAT32(pmp))
+			cn = getulong(&bp->b_data[bo]);
+		else
+			cn = getushort(&bp->b_data[bo]);
+		if (FAT12(pmp) && (prevcn & 1))
+			cn >>= 4;
+		cn &= pmp->pm_fatmask;
+
+		/*
+		 * Force the special cluster numbers
+		 * to be the same for all cluster sizes
+		 * to let the rest of msdosfs handle
+		 * all cases the same.
+		 */
+		if ((cn | ~pmp->pm_fatmask) >= CLUST_RSRVD)
+			cn |= ~pmp->pm_fatmask;
+     }
+
+     
+hiteof:
+    if (bp) {
+        updatefats(pmp, bp, bp_bn);
+    }
+func_ret:
+    pmp->pm_flags=pm_flags;
+    return;
+}
+
 /*
  * Update the fat.
  * If mirroring the fat, update all copies, with the first copy as last.
diff -ur msdosfs.old/msdosfs_vnops.c msdosfs.new/msdosfs_vnops.c
--- msdosfs.old/msdosfs_vnops.c	Thu Feb 12 18:39:32 2004
+++ msdosfs.new/msdosfs_vnops.c	Thu Feb 12 18:50:37 2004
@@ -875,6 +875,7 @@
 		(void) bwrite(bp);
 		goto loop;
 	}
+	fat_sync(vp,VTODE(vp));
 	while (vp->v_numoutput) {
 		vp->v_flag |= VBWAIT;
 		(void) tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "msdosfsn", 0);
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list