diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index c918cd74f65a..c384064befbb 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -112,8 +112,7 @@ static void ffs_blkfree_trim_task(void *ctx, int pending __unused); #ifdef INVARIANTS static int ffs_checkblk(struct inode *, ufs2_daddr_t, long); #endif -static ufs2_daddr_t ffs_clusteralloc(struct inode *, u_int, ufs2_daddr_t, int, - int); +static ufs2_daddr_t ffs_clusteralloc(struct inode *, u_int, ufs2_daddr_t, int); static ino_t ffs_dirpref(struct inode *); static ufs2_daddr_t ffs_fragextend(struct inode *, u_int, ufs2_daddr_t, int, int); @@ -460,10 +459,16 @@ nospace: SYSCTL_NODE(_vfs, OID_AUTO, ffs, CTLFLAG_RW, 0, "FFS filesystem"); static int doasyncfree = 1; -SYSCTL_INT(_vfs_ffs, OID_AUTO, doasyncfree, CTLFLAG_RW, &doasyncfree, 0, ""); +SYSCTL_INT(_vfs_ffs, OID_AUTO, doasyncfree, CTLFLAG_RW, &doasyncfree, 0, +"do not force synchronous writes when blocks are reallocated"); static int doreallocblks = 1; -SYSCTL_INT(_vfs_ffs, OID_AUTO, doreallocblks, CTLFLAG_RW, &doreallocblks, 0, ""); +SYSCTL_INT(_vfs_ffs, OID_AUTO, doreallocblks, CTLFLAG_RW, &doreallocblks, 0, +"enable block reallocation"); + +static int maxclustersearch = 10; +SYSCTL_INT(_vfs_ffs, OID_AUTO, maxclustersearch, CTLFLAG_RW, &maxclustersearch, +0, "max number of cylinder group to search for contigous blocks"); #ifdef DEBUG static volatile int prtrealloc = 0; @@ -510,7 +515,7 @@ ffs_reallocblks_ufs1(ap) ufs1_daddr_t soff, newblk, blkno; ufs2_daddr_t pref; struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp; - int i, len, start_lvl, end_lvl, ssize; + int i, cg, len, start_lvl, end_lvl, ssize; vp = ap->a_vp; ip = VTOI(vp); @@ -597,18 +602,39 @@ ffs_reallocblks_ufs1(ap) ebap = (ufs1_daddr_t *)ebp->b_data; } /* - * Find the preferred location for the cluster. + * Find the preferred location for the cluster. If we have not + * previously failed at this endeavor, then follow our standard + * preference calculation. If we have failed at it, then pick up + * where we last ended our search. */ UFS_LOCK(ump); - pref = ffs_blkpref_ufs1(ip, start_lbn, soff, sbap); + if (ip->i_nextclustercg == -1) + pref = ffs_blkpref_ufs1(ip, start_lbn, soff, sbap); + else + pref = cgdata(fs, ip->i_nextclustercg); /* * Search the block map looking for an allocation of the desired size. + * To avoid wasting too much time, we limit the number of cylinder + * groups that we will search. */ - if ((newblk = ffs_hashalloc(ip, dtog(fs, pref), pref, - len, len, ffs_clusteralloc)) == 0) { + cg = dtog(fs, pref); + for (i = min(maxclustersearch, fs->fs_ncg); i > 0; i--) { + if ((newblk = ffs_clusteralloc(ip, cg, pref, len)) != 0) + break; + cg += 1; + if (cg >= fs->fs_ncg) + cg = 0; + } + /* + * If we have failed in our search, record where we gave up for + * next time. Otherwise, fall back to our usual search citerion. + */ + if (newblk == 0) { + ip->i_nextclustercg = cg; UFS_UNLOCK(ump); goto fail; } + ip->i_nextclustercg = -1; /* * We have found a new contiguous block. * @@ -737,7 +763,7 @@ ffs_reallocblks_ufs2(ap) ufs_lbn_t start_lbn, end_lbn; ufs2_daddr_t soff, newblk, blkno, pref; struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp; - int i, len, start_lvl, end_lvl, ssize; + int i, cg, len, start_lvl, end_lvl, ssize; vp = ap->a_vp; ip = VTOI(vp); @@ -824,18 +850,39 @@ ffs_reallocblks_ufs2(ap) ebap = (ufs2_daddr_t *)ebp->b_data; } /* - * Find the preferred location for the cluster. + * Find the preferred location for the cluster. If we have not + * previously failed at this endeavor, then follow our standard + * preference calculation. If we have failed at it, then pick up + * where we last ended our search. */ UFS_LOCK(ump); - pref = ffs_blkpref_ufs2(ip, start_lbn, soff, sbap); + if (ip->i_nextclustercg == -1) + pref = ffs_blkpref_ufs2(ip, start_lbn, soff, sbap); + else + pref = cgdata(fs, ip->i_nextclustercg); /* * Search the block map looking for an allocation of the desired size. + * To avoid wasting too much time, we limit the number of cylinder + * groups that we will search. */ - if ((newblk = ffs_hashalloc(ip, dtog(fs, pref), pref, - len, len, ffs_clusteralloc)) == 0) { + cg = dtog(fs, pref); + for (i = min(maxclustersearch, fs->fs_ncg); i > 0; i--) { + if ((newblk = ffs_clusteralloc(ip, cg, pref, len)) != 0) + break; + cg += 1; + if (cg >= fs->fs_ncg) + cg = 0; + } + /* + * If we have failed in our search, record where we gave up for + * next time. Otherwise, fall back to our usual search citerion. + */ + if (newblk == 0) { + ip->i_nextclustercg = cg; UFS_UNLOCK(ump); goto fail; } + ip->i_nextclustercg = -1; /* * We have found a new contiguous block. * @@ -1786,12 +1833,11 @@ gotit: * take the first one that we find following bpref. */ static ufs2_daddr_t -ffs_clusteralloc(ip, cg, bpref, len, unused) +ffs_clusteralloc(ip, cg, bpref, len) struct inode *ip; u_int cg; ufs2_daddr_t bpref; int len; - int unused; { struct fs *fs; struct cg *cgp; diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index 88f952f0cd4e..2a368bd980fb 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -1688,6 +1688,7 @@ ffs_vgetf(mp, ino, flags, vpp, ffs_flags) ip->i_dev = dev; ip->i_number = ino; ip->i_ea_refs = 0; + ip->i_nextclustercg = -1; #ifdef QUOTA { int i; diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h index 37081d5fd261..cd7c47261534 100644 --- a/sys/ufs/ufs/inode.h +++ b/sys/ufs/ufs/inode.h @@ -87,6 +87,8 @@ struct inode { daddr_t *snapblklist; /* Collect expunged snapshot blocks. */ } i_un; + int i_nextclustercg; /* last cg searched for cluster */ + /* * Data for extended attribute modification. */