summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/ufs/ffs/ffs_alloc.c78
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c1
-rw-r--r--sys/ufs/ufs/inode.h2
3 files changed, 65 insertions, 16 deletions
diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c
index 69f3e99..9982139 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.
+ */
+ 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 = ffs_hashalloc(ip, dtog(fs, pref), pref,
- len, len, ffs_clusteralloc)) == 0) {
+ 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.
+ */
+ 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 = ffs_hashalloc(ip, dtog(fs, pref), pref,
- len, len, ffs_clusteralloc)) == 0) {
+ if (newblk == 0) {
+ ip->i_nextclustercg = cg;
UFS_UNLOCK(ump);
goto fail;
}
+ ip->i_nextclustercg = -1;
/*
* We have found a new contiguous block.
*
@@ -1785,12 +1832,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 c0b6c9f..a7ed993 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -1687,6 +1687,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 37081d5..cd7c472 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.
*/
OpenPOWER on IntegriCloud