Subject: Re: Still pagedaemon deadlocks!
To: None <current-users@NetBSD.org>
From: Bernd Ernesti <netbsd@lists.veego.de>
List: current-users
Date: 03/10/2004 10:15:06
--/04w6evG8XlLl3ft
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
On Wed, Mar 10, 2004 at 09:38:40AM +0100, Claudio M. Camacho wrote:
> Hello all, since 2 months, NetBSD -current is giving me some
> headaches. The problem is with uvm and pagedaemon.
pr#24443
Try the two patches: softdep.indirdep.diff and softdep.inodedep5.diff
which are attached to the pr or to this mail.
Bernd
--/04w6evG8XlLl3ft
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="softdep.indirdep.diff"
Index: ufs/ffs/ffs_softdep.c
===================================================================
--- ufs/ffs/ffs_softdep.c (revision 572)
+++ ufs/ffs/ffs_softdep.c (revision 573)
@@ -65,7 +65,6 @@ extern struct simplelock bqueue_slock; /
MALLOC_DEFINE(M_PAGEDEP, "pagedep", "file page dependencies");
MALLOC_DEFINE(M_INODEDEP, "inodedep", "Inode depependencies");
MALLOC_DEFINE(M_NEWBLK, "newblk", "New block allocation");
-MALLOC_DEFINE(M_INDIRDEP, "indirdep", "Indirect block dependencies");
/*
* These definitions need to be adapted to the system to which
@@ -3360,7 +3359,6 @@ softdep_disk_io_initiation(bp)
struct worklist *wk, *nextwk;
struct indirdep *indirdep;
struct inodedep *inodedep;
- caddr_t saveddata;
/*
* We only care about write operations. There should never
@@ -3411,15 +3409,11 @@ softdep_disk_io_initiation(bp)
/*
* Replace up-to-date version with safe version.
*/
- MALLOC(saveddata, caddr_t, bp->b_bcount, M_INDIRDEP,
- M_WAITOK);
ACQUIRE_LOCK(&lk);
indirdep->ir_state &= ~ATTACHED;
indirdep->ir_state |= UNDONE;
- indirdep->ir_saveddata = saveddata;
- bcopy(bp->b_data, indirdep->ir_saveddata, bp->b_bcount);
- bcopy(indirdep->ir_savebp->b_data, bp->b_data,
- bp->b_bcount);
+ indirdep->ir_saveddata = bp->b_data;
+ bp->b_data = indirdep->ir_savebp->b_data;
FREE_LOCK(&lk);
continue;
@@ -3962,8 +3956,7 @@ softdep_disk_write_complete(bp)
indirdep = WK_INDIRDEP(wk);
if (indirdep->ir_state & GOINGAWAY)
panic("disk_write_complete: indirdep gone");
- bcopy(indirdep->ir_saveddata, bp->b_data, bp->b_bcount);
- FREE(indirdep->ir_saveddata, M_INDIRDEP);
+ bp->b_data = indirdep->ir_saveddata;
indirdep->ir_saveddata = 0;
indirdep->ir_state &= ~UNDONE;
indirdep->ir_state |= ATTACHED;
--/04w6evG8XlLl3ft
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="softdep.inodedep5.diff"
Index: ffs_softdep.c
===================================================================
--- ffs_softdep.c (revision 573)
+++ ffs_softdep.c (revision 586)
@@ -481,6 +481,75 @@ softdep_freequeue_process(void)
}
}
+static char emerginoblk[MAXBSIZE];
+static int emerginoblk_inuse;
+static const struct buf *emerginoblk_origbp;
+static struct simplelock emerginoblk_slock = SIMPLELOCK_INITIALIZER;
+
+static __inline void *
+inodedep_allocdino(struct inodedep *inodedep, const struct buf *origbp,
+ size_t size)
+{
+ void *vp;
+ int s;
+
+ KASSERT(inodedep->id_savedino1 == NULL);
+
+ if (curproc != uvm.pagedaemon_proc)
+ return malloc(size, M_INODEDEP, M_WAITOK);
+
+ vp = malloc(size, M_INODEDEP, M_NOWAIT);
+ if (vp)
+ return vp;
+
+ s = splbio();
+ simple_lock(&emerginoblk_slock);
+ while (emerginoblk_inuse && emerginoblk_origbp != origbp)
+ ltsleep(&emerginoblk_inuse, PVM, "emdino", 0,
+ &emerginoblk_slock);
+ emerginoblk_origbp = origbp;
+ emerginoblk_inuse++;
+ KASSERT(emerginoblk_inuse <= sizeof(emerginoblk) /
+ MIN(sizeof(struct ufs1_dinode), sizeof(struct ufs2_dinode)));
+ simple_unlock(&emerginoblk_slock);
+ splx(s);
+
+ KASSERT(inodedep->id_savedino1 == NULL);
+
+ vp = emerginoblk +
+ size * ino_to_fsbo(inodedep->id_fs, inodedep->id_ino);
+ KASSERT((void *)&emerginoblk[0] <= vp);
+ KASSERT(vp < (void *)&emerginoblk[MAXBSIZE]);
+
+ return vp;
+}
+
+static __inline void
+inodedep_freedino(struct inodedep *inodedep)
+{
+ void *vp = inodedep->id_savedino1;
+
+ inodedep->id_savedino1 = NULL;
+ KASSERT(vp != NULL);
+ if (__predict_false((void *)&emerginoblk[0] <= vp &&
+ vp < (void *)&emerginoblk[MAXBSIZE])) {
+ int s;
+
+ KASSERT(emerginoblk_inuse > 0);
+ s = splbio();
+ simple_lock(&emerginoblk_slock);
+ emerginoblk_inuse--;
+ if (emerginoblk_inuse == 0)
+ wakeup(&emerginoblk_inuse);
+ simple_unlock(&emerginoblk_slock);
+ splx(s);
+
+ return;
+ }
+
+ free(vp, M_INODEDEP);
+}
+
/*
* Worklist queue management.
* These routines require that the lock be held.
@@ -2355,8 +2424,7 @@ check_inode_unwritten(inodedep)
if (inodedep->id_state & ONWORKLIST)
WORKLIST_REMOVE(&inodedep->id_list);
if (inodedep->id_savedino1 != NULL) {
- FREE(inodedep->id_savedino1, M_INODEDEP);
- inodedep->id_savedino1 = NULL;
+ inodedep_freedino(inodedep);
}
if (free_inodedep(inodedep) == 0)
panic("check_inode_unwritten: busy inode");
@@ -3517,8 +3585,8 @@ initiate_write_inodeblock_ufs1(inodedep,
if ((inodedep->id_state & DEPCOMPLETE) == 0) {
if (inodedep->id_savedino1 != NULL)
panic("initiate_write_inodeblock: already doing I/O");
- MALLOC(inodedep->id_savedino1, struct ufs1_dinode *,
- sizeof(struct ufs1_dinode), M_INODEDEP, M_WAITOK);
+ inodedep->id_savedino1 = inodedep_allocdino(inodedep, bp,
+ sizeof(struct ufs1_dinode));
*inodedep->id_savedino1 = *dp;
bzero((caddr_t)dp, sizeof(struct ufs1_dinode));
return;
@@ -3657,8 +3725,8 @@ initiate_write_inodeblock_ufs2(inodedep,
if ((inodedep->id_state & DEPCOMPLETE) == 0) {
if (inodedep->id_savedino2 != NULL)
panic("initiate_write_inodeblock_ufs2: I/O underway");
- MALLOC(inodedep->id_savedino2, struct ufs2_dinode *,
- sizeof(struct ufs2_dinode), M_INODEDEP, M_WAITOK);
+ inodedep->id_savedino2 = inodedep_allocdino(inodedep, bp,
+ sizeof(struct ufs2_dinode));
*inodedep->id_savedino2 = *dp;
bzero((caddr_t)dp, sizeof(struct ufs2_dinode));
return;
@@ -4144,8 +4212,7 @@ handle_written_inodeblock(inodedep, bp)
*dp1 = *inodedep->id_savedino1;
else
*dp2 = *inodedep->id_savedino2;
- FREE(inodedep->id_savedino1, M_INODEDEP);
- inodedep->id_savedino1 = NULL;
+ inodedep_freedino(inodedep);
if ((bp->b_flags & B_DELWRI) == 0)
stat_inode_bitmap++;
bdirty(bp);
--/04w6evG8XlLl3ft--