Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 21 Dec 2018 21:17:45 +0000 (UTC)
From:      Bruce Evans <bde@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r342357 - head/sys/fs/msdosfs
Message-ID:  <201812212117.wBLLHjXK035125@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: bde
Date: Fri Dec 21 21:17:45 2018
New Revision: 342357
URL: https://svnweb.freebsd.org/changeset/base/342357

Log:
  Fix clobbering of the fatchain cache for clustered i/o's when full
  clustering is not done.  The bug caused extreme slowness for large
  files in some cases.
  
  There is no way to tell VOP_BMAP() how many blocks are wanted, so for
  all file systems it has to waste time in some cases by searching for
  more contiguous blocks than will be accessed.  For msdosfs, it also
  clobbered the fatchain cache in these cases by advancing the cache to
  point to the chain entry for block that won't be read.  This makes
  the cache useless for the next sequential i/o (or VOP_BMAP()), so the
  fat chain is searched from the beginning.  The cache only has 1 relevant
  entry, so it is similarly useless for random i/o.
  
  Fix this by only advancing the cache to point to the chain entry for
  the first block that will be read.  Clustering uses results from
  VOP_BMAP(), so when more than 1 block is read by clustering, the cache
  is not advanced as optimally as before, but it is at most 1 cluster
  size behind and searching the chain through the blocks for this cluster
  doesn't take too long.

Modified:
  head/sys/fs/msdosfs/msdosfs_vnops.c

Modified: head/sys/fs/msdosfs/msdosfs_vnops.c
==============================================================================
--- head/sys/fs/msdosfs/msdosfs_vnops.c	Fri Dec 21 20:46:45 2018	(r342356)
+++ head/sys/fs/msdosfs/msdosfs_vnops.c	Fri Dec 21 21:17:45 2018	(r342357)
@@ -1740,6 +1740,7 @@ out:
 static int
 msdosfs_bmap(struct vop_bmap_args *ap)
 {
+	struct fatcache savefc;
 	struct denode *dep;
 	struct mount *mp;
 	struct msdosfsmount *pmp;
@@ -1766,6 +1767,20 @@ msdosfs_bmap(struct vop_bmap_args *ap)
 	if (error != 0 || (ap->a_runp == NULL && ap->a_runb == NULL))
 		return (error);
 
+	/*
+	 * Prepare to back out updates of the fatchain cache after the one
+	 * for the first block done by pcbmap() above.  Without the backout,
+	 * then whenever the caller doesn't do i/o to all of the blocks that
+	 * we find, the single useful cache entry would be too far in advance
+	 * of the actual i/o to work for the next sequential i/o.  Then the
+	 * FAT would be searched from the beginning.  With the backout, the
+	 * FAT is searched starting at most a few blocks early.  This wastes
+	 * much less time.  Time is also wasted finding more blocks than the
+	 * caller will do i/o to.  This is necessary because the runlength
+	 * parameters are output-only.
+	 */
+	savefc = dep->de_fc[FC_LASTMAP];
+
 	mp = vp->v_mount;
 	maxio = mp->mnt_iosize_max / mp->mnt_stat.f_iosize;
 	bnpercn = de_cn2bn(pmp, 1);
@@ -1787,6 +1802,7 @@ msdosfs_bmap(struct vop_bmap_args *ap)
 		}
 		*ap->a_runb = run - 1;
 	}
+	dep->de_fc[FC_LASTMAP] = savefc;
 	return (0);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201812212117.wBLLHjXK035125>