summaryrefslogtreecommitdiff
path: root/sys/ufs/ffs/ffs_softdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/ufs/ffs/ffs_softdep.c')
-rw-r--r--sys/ufs/ffs/ffs_softdep.c260
1 files changed, 188 insertions, 72 deletions
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index dcb58550fc1..45612cb8afd 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ffs_softdep.c,v 1.31 2001/12/19 08:58:07 art Exp $ */
+/* $OpenBSD: ffs_softdep.c,v 1.32 2002/01/23 21:24:02 millert Exp $ */
/*
* Copyright 1998, 2000 Marshall Kirk McKusick. All Rights Reserved.
*
@@ -53,6 +53,7 @@
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/proc.h>
+#include <sys/pool.h>
#include <sys/syslog.h>
#include <sys/systm.h>
#include <sys/vnode.h>
@@ -69,34 +70,42 @@
#define STATIC
/*
- * These definitions need to be adapted to the system to which
- * this file is being ported.
- */
-
-#define M_SOFTDEP_FLAGS (M_WAITOK)
-
-/*
* Mapping of dependency structure types to malloc types.
*/
-#define D_PAGEDEP M_PAGEDEP
-#define D_INODEDEP M_INODEDEP
-#define D_NEWBLK M_NEWBLK
-#define D_BMSAFEMAP M_BMSAFEMAP
-#define D_ALLOCDIRECT M_ALLOCDIRECT
-#define D_INDIRDEP M_INDIRDEP
-#define D_ALLOCINDIR M_ALLOCINDIR
-#define D_FREEFRAG M_FREEFRAG
-#define D_FREEBLKS M_FREEBLKS
-#define D_FREEFILE M_FREEFILE
-#define D_DIRADD M_DIRADD
-#define D_MKDIR M_MKDIR
-#define D_DIRREM M_DIRREM
+#define D_PAGEDEP 1
+#define D_INODEDEP 2
+#define D_NEWBLK 3
+#define D_BMSAFEMAP 4
+#define D_ALLOCDIRECT 5
+#define D_INDIRDEP 6
+#define D_ALLOCINDIR 7
+#define D_FREEFRAG 8
+#define D_FREEBLKS 9
+#define D_FREEFILE 10
+#define D_DIRADD 11
+#define D_MKDIR 12
+#define D_DIRREM 13
+#define D_LAST 13
/*
- * Names of malloc types.
+ * Names of softdep types.
*/
-extern char *memname[];
-#define TYPENAME(type) ((unsigned)(type) < M_LAST ? memname[type] : "???")
-#define DtoM(type) (type)
+const char *softdep_typenames[] = {
+ "invalid",
+ "pagedep",
+ "inodedep",
+ "newblk",
+ "bmsafemap",
+ "allocdirect",
+ "indirdep",
+ "allocindir",
+ "freefrag",
+ "freeblks",
+ "diradd",
+ "mkdir",
+ "dirrem",
+};
+#define TYPENAME(type) \
+ ((unsigned)(type) < D_LAST ? softdep_typenames[type] : "???")
/*
* Finding the current process.
*/
@@ -361,6 +370,97 @@ sema_release(semap)
}
/*
+ * Memory management.
+ */
+STATIC struct pool pagedep_pool;
+STATIC struct pool inodedep_pool;
+STATIC struct pool newblk_pool;
+STATIC struct pool bmsafemap_pool;
+STATIC struct pool allocdirect_pool;
+STATIC struct pool indirdep_pool;
+STATIC struct pool allocindir_pool;
+STATIC struct pool freefrag_pool;
+STATIC struct pool freeblks_pool;
+STATIC struct pool freefile_pool;
+STATIC struct pool diradd_pool;
+STATIC struct pool mkdir_pool;
+STATIC struct pool dirrem_pool;
+
+static __inline void
+softdep_free(struct worklist *item, int type)
+{
+
+ switch (type) {
+ case D_PAGEDEP:
+ pool_put(&pagedep_pool, item);
+ break;
+
+ case D_INODEDEP:
+ pool_put(&inodedep_pool, item);
+ break;
+
+ case D_BMSAFEMAP:
+ pool_put(&bmsafemap_pool, item);
+ break;
+
+ case D_ALLOCDIRECT:
+ pool_put(&allocdirect_pool, item);
+ break;
+
+ case D_INDIRDEP:
+ pool_put(&indirdep_pool, item);
+ break;
+
+ case D_ALLOCINDIR:
+ pool_put(&allocindir_pool, item);
+ break;
+
+ case D_FREEFRAG:
+ pool_put(&freefrag_pool, item);
+ break;
+
+ case D_FREEBLKS:
+ pool_put(&freeblks_pool, item);
+ break;
+
+ case D_FREEFILE:
+ pool_put(&freefile_pool, item);
+ break;
+
+ case D_DIRADD:
+ pool_put(&diradd_pool, item);
+ break;
+
+ case D_MKDIR:
+ pool_put(&mkdir_pool, item);
+ break;
+
+ case D_DIRREM:
+ pool_put(&dirrem_pool, item);
+ break;
+
+ default:
+#ifdef DEBUG
+ if (lk.lkt_held != -1)
+ FREE_LOCK(&lk);
+#endif
+ panic("softdep_free: unknown type %d", type);
+ }
+}
+
+struct workhead softdep_tofree;
+
+static __inline void
+softdep_queuefree(struct worklist *item)
+{
+ int s;
+
+ s = splbio();
+ LIST_INSERT_HEAD(&softdep_tofree, item, wk_list);
+ splx(s);
+}
+
+/*
* Worklist queue management.
* These routines require that the lock be held.
*/
@@ -373,7 +473,7 @@ sema_release(semap)
(item)->wk_state &= ~ONWORKLIST; \
LIST_REMOVE(item, wk_list); \
} while (0)
-#define WORKITEM_FREE(item, type) FREE(item, DtoM(type))
+#define WORKITEM_FREE(item, type) softdep_queuefree((struct worklist *)item)
#else /* DEBUG */
STATIC void worklist_insert __P((struct workhead *, struct worklist *));
@@ -382,7 +482,7 @@ STATIC void workitem_free __P((struct worklist *, int));
#define WORKLIST_INSERT(head, item) worklist_insert(head, item)
#define WORKLIST_REMOVE(item) worklist_remove(item)
-#define WORKITEM_FREE(item, type) workitem_free((struct worklist *)item, type)
+#define WORKITEM_FREE(item, type) workitem_free((struct worklist *)item)
STATIC void
worklist_insert(head, item)
@@ -416,9 +516,8 @@ worklist_remove(item)
}
STATIC void
-workitem_free(item, type)
+workitem_free(item)
struct worklist *item;
- int type;
{
if (item->wk_state & ONWORKLIST) {
@@ -426,12 +525,7 @@ workitem_free(item, type)
FREE_LOCK(&lk);
panic("workitem_free: still on list");
}
- if (item->wk_type != type) {
- if (lk.lkt_held != -1)
- FREE_LOCK(&lk);
- panic("workitem_free: type mismatch");
- }
- FREE(item, DtoM(type));
+ softdep_queuefree(item);
}
#endif /* DEBUG */
@@ -525,8 +619,19 @@ softdep_process_worklist(matchmnt)
struct mount *matchmnt;
{
struct proc *p = CURPROC;
- int matchcnt, loopcount;
+ int matchcnt, loopcount, s;
struct timeval starttime;
+ struct worklist *wk;
+
+ /*
+ * First process any items on the delay-free queue.
+ */
+ s = splbio();
+ while ((wk = LIST_FIRST(&softdep_tofree)) != NULL) {
+ LIST_REMOVE(wk, wk_list);
+ softdep_free(wk, wk->wk_type);
+ }
+ splx(s);
/*
* Record the process identifier of our caller so that we can give
@@ -906,8 +1011,7 @@ top:
ACQUIRE_LOCK(&lk);
goto top;
}
- MALLOC(pagedep, struct pagedep *, sizeof(struct pagedep), M_PAGEDEP,
- M_SOFTDEP_FLAGS);
+ pagedep = pool_get(&pagedep_pool, PR_WAITOK);
bzero(pagedep, sizeof(struct pagedep));
pagedep->pd_list.wk_type = D_PAGEDEP;
pagedep->pd_mnt = mp;
@@ -982,8 +1086,7 @@ top:
goto top;
}
num_inodedep += 1;
- MALLOC(inodedep, struct inodedep *, sizeof(struct inodedep),
- M_INODEDEP, M_SOFTDEP_FLAGS);
+ inodedep = pool_get(&inodedep_pool, PR_WAITOK);
inodedep->id_list.wk_type = D_INODEDEP;
inodedep->id_fs = fs;
inodedep->id_ino = inum;
@@ -1043,8 +1146,7 @@ top:
}
if (sema_get(&newblk_in_progress, 0) == 0)
goto top;
- MALLOC(newblk, struct newblk *, sizeof(struct newblk),
- M_NEWBLK, M_SOFTDEP_FLAGS);
+ newblk = pool_get(&newblk_pool, PR_WAITOK);
newblk->nb_state = 0;
newblk->nb_fs = fs;
newblk->nb_newblkno = newblkno;
@@ -1079,6 +1181,32 @@ softdep_initialize()
newblk_hashtbl = hashinit(64, M_NEWBLK, M_WAITOK, &newblk_hash);
sema_init(&newblk_in_progress, "newblk", PRIBIO, 0);
timeout_set(&proc_waiting_timeout, pause_timer, 0);
+ pool_init(&pagedep_pool, sizeof(struct pagedep), 0, 0, 0,
+ "pagedeppl", &pool_allocator_nointr);
+ pool_init(&inodedep_pool, sizeof(struct inodedep), 0, 0, 0,
+ "inodedeppl", &pool_allocator_nointr);
+ pool_init(&newblk_pool, sizeof(struct newblk), 0, 0, 0,
+ "newblkpl", &pool_allocator_nointr);
+ pool_init(&bmsafemap_pool, sizeof(struct bmsafemap), 0, 0, 0,
+ "bmsafemappl", &pool_allocator_nointr);
+ pool_init(&allocdirect_pool, sizeof(struct allocdirect), 0, 0, 0,
+ "allocdirectpl", &pool_allocator_nointr);
+ pool_init(&indirdep_pool, sizeof(struct indirdep), 0, 0, 0,
+ "indirdeppl", &pool_allocator_nointr);
+ pool_init(&allocindir_pool, sizeof(struct allocindir), 0, 0, 0,
+ "allocindirpl", &pool_allocator_nointr);
+ pool_init(&freefrag_pool, sizeof(struct freefrag), 0, 0, 0,
+ "freefragpl", &pool_allocator_nointr);
+ pool_init(&freeblks_pool, sizeof(struct freeblks), 0, 0, 0,
+ "freeblkspl", &pool_allocator_nointr);
+ pool_init(&freefile_pool, sizeof(struct freefile), 0, 0, 0,
+ "freefilepl", &pool_allocator_nointr);
+ pool_init(&diradd_pool, sizeof(struct diradd), 0, 0, 0,
+ "diraddpl", &pool_allocator_nointr);
+ pool_init(&mkdir_pool, sizeof(struct mkdir), 0, 0, 0,
+ "mkdirpl", &pool_allocator_nointr);
+ pool_init(&dirrem_pool, sizeof(struct dirrem), 0, 0, 0,
+ "dirrempl", &pool_allocator_nointr);
}
/*
@@ -1237,8 +1365,7 @@ bmsafemap_lookup(bp)
if (wk->wk_type == D_BMSAFEMAP)
return (WK_BMSAFEMAP(wk));
FREE_LOCK(&lk);
- MALLOC(bmsafemap, struct bmsafemap *, sizeof(struct bmsafemap),
- M_BMSAFEMAP, M_SOFTDEP_FLAGS);
+ bmsafemap = pool_get(&bmsafemap_pool, PR_WAITOK);
bmsafemap->sm_list.wk_type = D_BMSAFEMAP;
bmsafemap->sm_list.wk_state = 0;
bmsafemap->sm_buf = bp;
@@ -1297,8 +1424,7 @@ softdep_setup_allocdirect(ip, lbn, newblkno, oldblkno, newsize, oldsize, bp)
struct pagedep *pagedep;
struct newblk *newblk;
- MALLOC(adp, struct allocdirect *, sizeof(struct allocdirect),
- M_ALLOCDIRECT, M_SOFTDEP_FLAGS);
+ adp = pool_get(&allocdirect_pool, PR_WAITOK);
bzero(adp, sizeof(struct allocdirect));
adp->ad_list.wk_type = D_ALLOCDIRECT;
adp->ad_lbn = lbn;
@@ -1329,7 +1455,7 @@ softdep_setup_allocdirect(ip, lbn, newblkno, oldblkno, newsize, oldsize, bp)
LIST_INSERT_HEAD(&bmsafemap->sm_allocdirecthd, adp, ad_deps);
}
LIST_REMOVE(newblk, nb_hash);
- FREE(newblk, M_NEWBLK);
+ pool_put(&newblk_pool, newblk);
if (bp == NULL) {
/*
@@ -1460,8 +1586,7 @@ newfreefrag(ip, blkno, size)
fs = ip->i_fs;
if (fragnum(fs, blkno) + numfrags(fs, size) > fs->fs_frag)
panic("newfreefrag: frag size");
- MALLOC(freefrag, struct freefrag *, sizeof(struct freefrag),
- M_FREEFRAG, M_SOFTDEP_FLAGS);
+ freefrag = pool_get(&freefrag_pool, PR_WAITOK);
freefrag->ff_list.wk_type = D_FREEFRAG;
freefrag->ff_state = ip->i_ffs_uid & ~ONWORKLIST; /* XXX - used below */
freefrag->ff_inum = ip->i_number;
@@ -1489,7 +1614,7 @@ handle_workitem_freefrag(freefrag)
tip.i_number = freefrag->ff_inum;
tip.i_ffs_uid = freefrag->ff_state & ~ONWORKLIST; /* XXX - set above */
ffs_blkfree(&tip, freefrag->ff_blkno, freefrag->ff_fragsize);
- FREE(freefrag, M_FREEFRAG);
+ pool_put(&freefrag_pool, freefrag);
}
/*
@@ -1529,8 +1654,7 @@ newallocindir(ip, ptrno, newblkno, oldblkno)
{
struct allocindir *aip;
- MALLOC(aip, struct allocindir *, sizeof(struct allocindir),
- M_ALLOCINDIR, M_SOFTDEP_FLAGS);
+ aip = pool_get(&allocindir_pool, PR_WAITOK);
bzero(aip,sizeof(struct allocindir));
aip->ai_list.wk_type = D_ALLOCINDIR;
aip->ai_state = ATTACHED;
@@ -1649,7 +1773,7 @@ setup_allocindir_phase2(bp, ip, aip)
aip, ai_deps);
}
LIST_REMOVE(newblk, nb_hash);
- FREE(newblk, M_NEWBLK);
+ pool_put(&newblk_pool, newblk);
aip->ai_indirdep = indirdep;
/*
* Check to see if there is an existing dependency
@@ -1685,12 +1809,11 @@ setup_allocindir_phase2(bp, ip, aip)
if (newindirdep) {
if (indirdep->ir_savebp != NULL)
brelse(newindirdep->ir_savebp);
- WORKITEM_FREE((caddr_t)newindirdep, D_INDIRDEP);
+ WORKITEM_FREE(newindirdep, D_INDIRDEP);
}
if (indirdep)
break;
- MALLOC(newindirdep, struct indirdep *, sizeof(struct indirdep),
- M_INDIRDEP, M_SOFTDEP_FLAGS);
+ newindirdep = pool_get(&indirdep_pool, PR_WAITOK);
newindirdep->ir_list.wk_type = D_INDIRDEP;
newindirdep->ir_state = ATTACHED;
LIST_INIT(&newindirdep->ir_deplisthd);
@@ -1753,8 +1876,7 @@ softdep_setup_freeblocks(ip, length)
fs = ip->i_fs;
if (length != 0)
panic("softdep_setup_freeblocks: non-zero length");
- MALLOC(freeblks, struct freeblks *, sizeof(struct freeblks),
- M_FREEBLKS, M_SOFTDEP_FLAGS);
+ freeblks = pool_get(&freeblks_pool, PR_WAITOK);
bzero(freeblks, sizeof(struct freeblks));
freeblks->fb_list.wk_type = D_FREEBLKS;
freeblks->fb_uid = ip->i_ffs_uid;
@@ -2006,8 +2128,7 @@ softdep_freefile(pvp, ino, mode)
/*
* This sets up the inode de-allocation dependency.
*/
- MALLOC(freefile, struct freefile *, sizeof(struct freefile),
- M_FREEFILE, M_SOFTDEP_FLAGS);
+ freefile = pool_get(&freefile_pool, PR_WAITOK);
freefile->fx_list.wk_type = D_FREEFILE;
freefile->fx_list.wk_state = 0;
freefile->fx_mode = mode;
@@ -2329,8 +2450,7 @@ softdep_setup_directory_add(bp, dp, diroffset, newinum, newdirbp)
fs = dp->i_fs;
lbn = lblkno(fs, diroffset);
offset = blkoff(fs, diroffset);
- MALLOC(dap, struct diradd *, sizeof(struct diradd), M_DIRADD,
- M_SOFTDEP_FLAGS);
+ dap = pool_get(&diradd_pool, PR_WAITOK);
bzero(dap,sizeof(struct diradd));
dap->da_list.wk_type = D_DIRADD;
dap->da_offset = offset;
@@ -2341,13 +2461,11 @@ softdep_setup_directory_add(bp, dp, diroffset, newinum, newdirbp)
ACQUIRE_LOCK(&lk);
} else {
dap->da_state |= MKDIR_BODY | MKDIR_PARENT;
- MALLOC(mkdir1, struct mkdir *, sizeof(struct mkdir), M_MKDIR,
- M_SOFTDEP_FLAGS);
+ mkdir1 = pool_get(&mkdir_pool, PR_WAITOK);
mkdir1->md_list.wk_type = D_MKDIR;
mkdir1->md_state = MKDIR_BODY;
mkdir1->md_diradd = dap;
- MALLOC(mkdir2, struct mkdir *, sizeof(struct mkdir), M_MKDIR,
- M_SOFTDEP_FLAGS);
+ mkdir2 = pool_get(&mkdir_pool, PR_WAITOK);
mkdir2->md_list.wk_type = D_MKDIR;
mkdir2->md_state = MKDIR_PARENT;
mkdir2->md_diradd = dap;
@@ -2583,8 +2701,7 @@ newdirrem(bp, dp, ip, isrmdir, prevdirremp)
if (num_dirrem > max_softdeps / 2)
(void) request_cleanup(FLUSH_REMOVE, 0);
num_dirrem += 1;
- MALLOC(dirrem, struct dirrem *, sizeof(struct dirrem),
- M_DIRREM, M_SOFTDEP_FLAGS);
+ dirrem = pool_get(&dirrem_pool, PR_WAITOK);
bzero(dirrem,sizeof(struct dirrem));
dirrem->dm_list.wk_type = D_DIRREM;
dirrem->dm_state = isrmdir ? RMDIR : 0;
@@ -2684,8 +2801,7 @@ softdep_setup_directory_change(bp, dp, ip, newinum, isrmdir)
* Whiteouts do not need diradd dependencies.
*/
if (newinum != WINO) {
- MALLOC(dap, struct diradd *, sizeof(struct diradd),
- M_DIRADD, M_SOFTDEP_FLAGS);
+ dap = pool_get(&diradd_pool, PR_WAITOK);
bzero(dap,sizeof(struct diradd));
dap->da_list.wk_type = D_DIRADD;
dap->da_state = DIRCHG | ATTACHED | DEPCOMPLETE;
@@ -3004,7 +3120,7 @@ softdep_disk_io_initiation(bp)
* Replace up-to-date version with safe version.
*/
MALLOC(indirdep->ir_saveddata, caddr_t, bp->b_bcount,
- M_INDIRDEP, M_SOFTDEP_FLAGS);
+ M_INDIRDEP, M_WAITOK);
ACQUIRE_LOCK(&lk);
indirdep->ir_state &= ~ATTACHED;
indirdep->ir_state |= UNDONE;
@@ -3106,7 +3222,7 @@ initiate_write_inodeblock(inodedep, bp)
if (inodedep->id_savedino != NULL)
panic("initiate_write_inodeblock: already doing I/O");
MALLOC(inodedep->id_savedino, struct dinode *,
- sizeof(struct dinode), M_INODEDEP, M_SOFTDEP_FLAGS);
+ sizeof(struct dinode), M_INODEDEP, M_WAITOK);
*inodedep->id_savedino = *dp;
bzero((caddr_t)dp, sizeof(struct dinode));
return;