diff options
| author | Tor Egge <tegge@FreeBSD.org> | 2005-09-20 22:37:54 +0000 |
|---|---|---|
| committer | Tor Egge <tegge@FreeBSD.org> | 2005-09-20 22:37:54 +0000 |
| commit | bd1c32850b28717c349af7ff4ef5b5b4598949e2 (patch) | |
| tree | eb35a9c59e174c081207aa29e751e7aa0f39d8ca /sys | |
| parent | 8ee23ab4f5b1c878e1b1bdcc8228f55d8b83290f (diff) | |
Notes
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/ufs/ffs/ffs_softdep.c | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index 611614bb4fad..3045c4c5335c 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -2065,6 +2065,15 @@ check_inode_unwritten(inodedep) TAILQ_FIRST(&inodedep->id_newinoupdt) != NULL || inodedep->id_nlinkdelta != 0) return (0); + + /* + * Another process might be in initiate_write_inodeblock + * trying to allocate memory without holding "Softdep Lock". + */ + if ((inodedep->id_state & IOSTARTED) != 0 && + inodedep->id_savedino == NULL) + return (0); + inodedep->id_state |= ALLCOMPLETE; LIST_REMOVE(inodedep, id_deps); inodedep->id_buf = NULL; @@ -2930,6 +2939,21 @@ handle_workitem_freefile(freefile) WORKITEM_FREE(freefile, D_FREEFILE); } + +/* + * Helper function which unlinks marker element from work list and returns + * the next element on the list. + */ +static __inline struct worklist * +markernext(struct worklist *marker) +{ + struct worklist *next; + + next = LIST_NEXT(marker, wk_list); + LIST_REMOVE(marker, wk_list); + return next; +} + /* * Disk writes. * @@ -2956,7 +2980,8 @@ static void softdep_disk_io_initiation(bp) struct buf *bp; /* structure describing disk write to occur */ { - struct worklist *wk, *nextwk; + struct worklist *wk; + struct worklist marker; struct indirdep *indirdep; /* @@ -2965,11 +2990,16 @@ softdep_disk_io_initiation(bp) */ if (bp->b_flags & B_READ) panic("softdep_disk_io_initiation: read"); + + marker.wk_type = D_LAST + 1; /* Not a normal workitem */ + PHOLD(curproc); /* Don't swap out kernel stack */ + /* * Do any necessary pre-I/O processing. */ - for (wk = LIST_FIRST(&bp->b_dep); wk; wk = nextwk) { - nextwk = LIST_NEXT(wk, wk_list); + for (wk = LIST_FIRST(&bp->b_dep); wk != NULL; + wk = markernext(&marker)) { + LIST_INSERT_AFTER(wk, &marker, wk_list); switch (wk->wk_type) { case D_PAGEDEP: @@ -3024,6 +3054,7 @@ softdep_disk_io_initiation(bp) /* NOTREACHED */ } } + PRELE(curproc); /* Allow swapout of kernel stack */ } /* @@ -3107,6 +3138,7 @@ initiate_write_inodeblock(inodedep, bp) sizeof(struct dinode), M_INODEDEP, M_SOFTDEP_FLAGS); *inodedep->id_savedino = *dp; bzero((caddr_t)dp, sizeof(struct dinode)); + dp->di_gen = inodedep->id_savedino->di_gen; return; } /* |
