tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: Bogus KASSERT() in LFS?
On Wed, 5 Jan 2011, Martin Husemann wrote:
> On Wed, Jan 05, 2011 at 04:25:09PM +0000, Eduardo Horvath wrote:
> > I think you're right. While I'm pretty sure that curpg won't be NULL on
> > the first iteration, I think it can be NULL on subsequent iterations. I'd
> > commit that change.
>
> It shouldn't get there on subsequent iterations if it pulled a NULL out
> of the TAILQ because it explicitily breaks out of the loop in that case.
>
> Why do you think it can't happen initially?
Looking at the code:
1845: top:
1846: by_list = (vp->v_uobj.uo_npages <=
1847: ((endoffset - startoffset) >> PAGE_SHIFT) *
1848: UVM_PAGE_TREE_PENALTY);
1849: any_dirty = 0;
1850:
1851: if (by_list) {
1852: curpg = TAILQ_FIRST(&vp->v_uobj.memq);
If by_list is set we'll always get here, and I don't think we'd be called
if the vnode had no pages at all, 'cause lfs_putpages checks for that
condition and exits immediately if it's true:
2062: * If there are no pages, don't do anything.
2063: */
2064: if (vp->v_uobj.uo_npages == 0) {
2065: if (TAILQ_EMPTY(&vp->v_uobj.memq) &&
2066: (vp->v_iflag & VI_ONWORKLST) &&
2067: LIST_FIRST(&vp->v_dirtyblkhd) == NULL) {
2068: vp->v_iflag &= ~VI_WRMAPDIRTY;
2069: vn_syncer_remove_from_worklist(vp);
2070: }
2071: mutex_exit(&vp->v_interlock);
2072:
2073: /* Remove us from paging queue, if we were on it */
2074: mutex_enter(&lfs_lock);
2075: if (ip->i_flags & IN_PAGING) {
2076: ip->i_flags &= ~IN_PAGING;
2077: TAILQ_REMOVE(&fs->lfs_pchainhd, ip, i_lfs_pchain);
2078: }
2079: mutex_exit(&lfs_lock);
2080: return 0;
2081: }
Later:
1853: else {
1854: soff = startoffset;
1855: }
1856: while (by_list || soff < MIN(blkeof, endoffset)) {
1857: if (by_list) {
So if by_list is true, curpg should not be NULL on the first iteration.
However....
1858: /*
1859: * Find the first page in a block. Skip
1860: * blocks outside our area of interest or beyond
1861: * the end of file.
1862: */
1863: KASSERT((curpg->flags & PG_MARKER) == 0);
1864: if (pages_per_block > 1) {
At the bottom of the loop:
1972: if (by_list) {
1973: curpg = TAILQ_NEXT(curpg, listq.queue);
1974: } else {
1975: soff += MAX(PAGE_SIZE, fs->lfs_bsize);
1976: }
1977: }
If we got to the end of the queue, curpg could be NULL at the next
iteration.
(Sigh. One of these days I need to get inspired to give LFS an overhaul.
Recursion in the kernel is not good, and the code needs to be robust
enough to recover from a corrupted ifile. In theory, LFS should be much
more robust than FFS even with logging, since even if you lose parts of
the platter you may be able to roll back to older versions of a file....)
Eduardo
Home |
Main Index |
Thread Index |
Old Index