/* * Roll the embedded log, if any, and set up the global variables * islog and islogok. */ static int logsetup(caddr_t devstr) { void *buf; extent_block_t *ebp; ml_unit_t *ul; ml_odunit_t *ud; void *ud_buf; int badlog; islog = islogok = 0; if (bflag != 0) return (1); /* can't roll log while alternate sb specified */ /* * Roll the log, if any. A bad sb implies we'll be using * an alternate sb as far as logging goes, so just fail back * to the caller if we can't read the default sb. Suppress * complaints, because the caller will be reading the same * superblock again and running full verification on it, so * whatever is bad will be reported then. */ sblock.fs_logbno = 0; badlog = 0; if (!read_super_block(0)) return (1); /* * Roll the log in 3 cases: * 1. If it's unmounted (mount_point == NULL) and it's not marked * as fully rolled (sblock.fs_rolled != FS_ALL_ROLLED) * 2. If it's mounted and anything other than a sanity * check fsck (mflag) is being done, as we have the current * super block. Note, only a sanity check is done for * root/usr at boot. If a roll were done then the expensive * ufs_flush() gets called, leading to a slower boot. * 3. If anything other then a sanity check (mflag) is being done * to a mounted filesystem while it is in read-only state * (e.g. root during early boot stages) we have to detect this * and have to roll the log as well. NB. the read-only mount * will flip fs_clean from FSLOG to FSSTABLE and marks the * log as FS_NEED_ROLL. */ if (sblock.fs_logbno && (((mount_point == NULL) && (sblock.fs_rolled != FS_ALL_ROLLED)) || ((mount_point != NULL) && !mflag))) { int roll_log_err = 0; if (sblock.fs_ronly && (sblock.fs_clean == FSSTABLE) && (sblock.fs_state + sblock.fs_time == FSOKAY)) { /* * roll the log without a mount */ flush_fs(); } if (sblock.fs_clean == FSLOG && (sblock.fs_state + sblock.fs_time == FSOKAY)) { if (rl_roll_log(devstr) != RL_SUCCESS) roll_log_err = 1; } if (roll_log_err) { (void) printf("Can't roll the log for %s.\n", devstr); /* * There are two cases where we want to set * an error code and return: * - We're preening * - We're not on a live root and the user * chose *not* to ignore the log * Otherwise, we want to mark the log as bad * and continue to check the filesystem. This * has the side effect of destroying the log. */ if (preen || (!hotroot && reply( "DISCARDING THE LOG MAY DISCARD PENDING TRANSACTIONS.\n" "DISCARD THE LOG AND CONTINUE") == 0)) { exitstat = EXERRFATAL; return (0); } ++badlog; } } /* Logging UFS may be enabled */ if (sblock.fs_logbno) { ++islog; /* log is not okay; check the fs */ if (FSOKAY != (sblock.fs_state + sblock.fs_time)) return (1); /* * If logging or (stable and mounted) then continue */ if (!((sblock.fs_clean == FSLOG) || (sblock.fs_clean == FSSTABLE) && (mount_point != NULL))) return (1); /* get the log allocation block */ buf = malloc(dev_bsize); if (buf == NULL) { return (1); } ud_buf = malloc(dev_bsize); if (ud_buf == NULL) { free(buf); return (1); } (void) fsck_bread(fsreadfd, buf, logbtodb(&sblock, sblock.fs_logbno), dev_bsize); ebp = (extent_block_t *)buf; /* log allocation block is not okay; check the fs */ if (ebp->type != LUFS_EXTENTS) { free(buf); free(ud_buf); return (1); } /* get the log state block(s) */ if (fsck_bread(fsreadfd, ud_buf, (logbtodb(&sblock, ebp->extents[0].pbno)), dev_bsize)) { (void) fsck_bread(fsreadfd, ud_buf, (logbtodb(&sblock, ebp->extents[0].pbno)) + 1, dev_bsize); } ud = (ml_odunit_t *)ud_buf; ul = (ml_unit_t *)malloc(sizeof (*ul)); if (ul == NULL) { free(buf); free(ud_buf); return (1); } ul->un_ondisk = *ud; /* log state is okay; don't need to check the fs */ if ((ul->un_chksum == ul->un_head_ident + ul->un_tail_ident) && (ul->un_version == LUFS_VERSION_LATEST) && (ul->un_badlog == 0) && (!badlog)) { ++islogok; } free(ud_buf); free(buf); free(ul); } return (1); }
/* ARGSUSED2 */ static int lqfs_alloc(qfsvfs_t *qfsvfsp, struct fiolog *flp, cred_t *cr) { int error = 0; buf_t *bp = NULL; extent_t *ep, *nep; extent_block_t *ebp; fs_lqfs_common_t *fs = VFS_FS_PTR(qfsvfsp); daddr_t fno; /* in frags */ #ifdef LUFS daddr_t bno; /* in disk blocks */ #endif /* LUFS */ int32_t logbno = INT32_C(0); /* will be fs_logbno */ ushort_t logord = 0; /* will be fs_logord */ inode_t *ip = NULL; #ifndef LUFS sam_bn_t bno; #endif /* LUFS */ size_t nb = flp->nbytes_actual; size_t tb = 0; int ord = 0; uchar_t save_unit; /* * Mark the file system as FSACTIVE */ UL_SBOWNER_SET(qfsvfsp, curthread); VFS_LOCK_MUTEX_ENTER(qfsvfsp); LQFS_SET_FS_CLEAN(fs, FSACTIVE); #ifdef LUFS qfs_sbwrite(qfsvfsp); #else sam_update_sblk(qfsvfsp, 0, 0, TRUE); sam_update_sblk(qfsvfsp, 0, 1, TRUE); #endif /* LUFS */ VFS_LOCK_MUTEX_EXIT(qfsvfsp); UL_SBOWNER_SET(qfsvfsp, -1); /* * Allocate the allocation block (need dummy shadow inode; * we use a shadow inode so the quota sub-system ignores * the block allocations.) * superblock -> one block of extents -> log data */ #ifdef LUFS ip = qfs_alloc_inode(qfsvfsp, QFSROOTINO); ip->i_mode = IFSHAD; /* make the dummy a shadow inode */ #else /* * Although QFS has "extension" inodes, it doesn't really implement * the concept of "shadow" inodes. We can't bypass having the quota * system track the allocation of log blocks. For now, use the * .inodes inode (SAM_INO_INO) to which we we will allocate space * for a UFS-like log of the requested size. Allocate space at mount * time BEFORE the quota system is initialized. */ ip = qfsvfsp->mi.m_inodir; #endif /* LUFS */ rw_enter(&ip->i_contents, RW_WRITER); #ifdef LUFS /* Allocate first log block (extent info). */ fno = contigpref(qfsvfsp, nb + FS_BSIZE(fs)); error = alloc(ip, fno, FS_BSIZE(fs), &fno, cr); #else save_unit = ip->di.unit; ip->di.unit = 0; if ((error = sam_alloc_block(ip, SM, &bno, &ord)) == 0) { /* Convert 4K block offset to 1K frag offset. */ fno = fsblktologb(fs, bno); } #endif /* LUFS */ if (error) { goto errout; } /* Convert 1K frag offset to 512B disk block offset. */ bno = fsbtodb(fs, fno); sam_bread_db(qfsvfsp, qfsvfsp->mi.m_fs[ord].dev, bno, FS_BSIZE(fs), &bp); if (bp->b_flags & B_ERROR) { error = EIO; goto errout; } ebp = (void *)bp->b_un.b_addr; ebp->type = LQFS_EXTENTS; ebp->nextbno = UINT32_C(0); ebp->nextord = 0; ebp->nextents = UINT32_C(0); ebp->chksum = INT32_C(0); #ifdef LUFS if (fs->fs_magic == SAM_MAGIC) { logbno = bno; } else { #endif /* LUFS */ logbno = dbtofsb(fs, bno); #ifdef LUFS } #endif /* LUFS */ logord = (ushort_t)ord; /* * Initialize the first extent */ ep = &ebp->extents[0]; #ifdef LUFS error = alloc(ip, fno + FS_FRAG(fs), FS_BSIZE(fs), &fno, cr); #else ip->di.unit = 0; if ((error = sam_alloc_block(ip, SM, &bno, &ord)) == 0) { /* Convert 4K block offset to 1K block (frag) offset. */ fno = fsblktologb(fs, bno); } #endif /* LUFS */ if (error) { goto errout; } /* Convert frag offset to physical disk block (512B block) offset. */ bno = fsbtodb(fs, fno); ep->lbno = UINT32_C(0); #ifdef LUFS if (fs->fs_magic == SAM_MAGIC) { ep->pbno = (uint32_t)bno; } else { #endif /* LUFS */ ep->pbno = (uint32_t)fno; #ifdef LUFS } #endif /* LUFS */ ep->nbno = (uint32_t)fsbtodb(fs, FS_FRAG(fs)); /* Has 8 disk blocks */ ep->ord = ord; ebp->nextents = UINT32_C(1); tb = FS_BSIZE(fs); nb -= FS_BSIZE(fs); while (nb) { #ifdef LUFS error = alloc(ip, fno + FS_FRAG(fs), FS_BSIZE(fs), &fno, cr); #else ip->di.unit = 0; error = sam_alloc_block(ip, SM, &bno, &ord); if (!error) { fno = fsblktologb(fs, bno); } #endif /* LUFS */ if (error) { if (tb < ldl_minlogsize) { goto errout; } error = 0; break; } bno = fsbtodb(fs, fno); if ((ep->ord == ord) && ((daddr_t)((logbtodb(fs, ep->pbno) + ep->nbno) == bno))) { ep->nbno += (uint32_t)(fsbtodb(fs, FS_FRAG(fs))); } else { nep = ep + 1; if ((caddr_t)(nep + 1) > (bp->b_un.b_addr + FS_BSIZE(fs))) { #ifdef LUFS free(ip, fno, FS_BSIZE(fs), 0); #else sam_free_block(qfsvfsp, SM, logbtofsblk(fs, fno), ord); #endif /* LUFS */ break; } nep->lbno = ep->lbno + ep->nbno; #ifdef LUFS if (fs->fs_magic == SAM_MAGIC) { nep->pbno = (uint32_t)bno; } else { #endif /* LUFS */ nep->pbno = (uint32_t)fno; #ifdef LUFS } #endif /* LUFS */ nep->nbno = (uint32_t)(fsbtodb(fs, FS_FRAG(fs))); nep->ord = ord; ebp->nextents++; ep = nep; } tb += FS_BSIZE(fs); nb -= FS_BSIZE(fs); } ebp->nbytes = (uint32_t)tb; setsum(&ebp->chksum, (int32_t *)(void *)bp->b_un.b_addr, FS_BSIZE(fs)); if ((error = SAM_BWRITE2(qfsvfsp, bp)) != 0) { goto errout; } /* * Initialize the first two sectors of the log */ error = lqfs_initialize(qfsvfsp, logbtodb(fs, ebp->extents[0].pbno), ebp->extents[0].ord, tb, flp); if (error) { goto errout; } /* * We are done initializing the allocation block and the log */ brelse(bp); bp = NULL; /* * Update the superblock and push the dirty metadata */ UL_SBOWNER_SET(qfsvfsp, curthread); #ifdef LUFS sbupdate(qfsvfsp->vfs_vfs); #else sam_update_sblk(qfsvfsp, 0, 0, TRUE); #endif /* LUFS */ UL_SBOWNER_SET(qfsvfsp, -1); bflush(qfsvfsp->mi.m_fs[logord].dev); error = bfinval(qfsvfsp->mi.m_fs[logord].dev, 1); if (error) { goto errout; } #ifdef LUFS if (qfsvfsp->vfs_bufp->b_flags & B_ERROR) { error = EIO; goto errout; } #endif /* LUFS */ /* * Everything is safely on disk; update log space pointer in sb */ UL_SBOWNER_SET(qfsvfsp, curthread); VFS_LOCK_MUTEX_ENTER(qfsvfsp); LQFS_SET_LOGBNO(fs, (uint32_t)logbno); LQFS_SET_LOGORD(fs, logord); #ifdef LUFS qfs_sbwrite(qfsvfsp); #else sam_update_sblk(qfsvfsp, 0, 0, TRUE); sam_update_sblk(qfsvfsp, 0, 1, TRUE); #endif /* LUFS */ VFS_LOCK_MUTEX_EXIT(qfsvfsp); UL_SBOWNER_SET(qfsvfsp, -1); ip->di.unit = save_unit; /* * Free the dummy inode */ rw_exit(&ip->i_contents); #ifdef LUFS qfs_free_inode(ip); #endif /* LUFS */ /* inform user of real log size */ flp->nbytes_actual = tb; return (0); errout: /* * Free all resources */ if (bp) { brelse(bp); } if (logbno) { LQFS_SET_LOGBNO(fs, logbno); LQFS_SET_LOGORD(fs, logord); (void) lqfs_free(qfsvfsp); } if (ip) { ip->di.unit = save_unit; rw_exit(&ip->i_contents); #ifdef LUFS qfs_free_inode(ip); #endif /* LUFS */ } return (error); }
int lqfs_snarf(qfsvfs_t *qfsvfsp, fs_lqfs_common_t *fs, int ronly) { buf_t *bp, *tbp; ml_unit_t *ul; extent_block_t *ebp; ic_extent_block_t *nebp; size_t nb; daddr_t bno; /* in disk blocks */ int ord; int i; /* LINTED: warning: logical expression always true: op "||" */ ASSERT(sizeof (ml_odunit_t) < DEV_BSIZE); /* * Get the allocation table * During a remount the superblock pointed to by the qfsvfsp * is out of date. Hence the need for the ``new'' superblock * pointer, fs, passed in as a parameter. */ sam_bread_db(qfsvfsp, qfsvfsp->mi.m_fs[LQFS_GET_LOGORD(fs)].dev, logbtodb(fs, LQFS_GET_LOGBNO(fs)), FS_BSIZE(fs), &bp); if (bp->b_flags & B_ERROR) { brelse(bp); return (EIO); } ebp = (void *)bp->b_un.b_addr; if (!checksum(&ebp->chksum, (int32_t *)(void *)bp->b_un.b_addr, FS_BSIZE(fs))) { brelse(bp); return (ENODEV); } /* * It is possible to get log blocks with all zeros. * We should also check for nextents to be zero in such case. */ if (ebp->type != LQFS_EXTENTS || ebp->nextents == 0) { brelse(bp); return (EDOM); } /* * Put allocation into memory. This requires conversion between * on the ondisk format of the extent (type extent_t) and the * in-core format of the extent (type ic_extent_t). The * difference is the in-core form of the extent block stores * the physical offset of the extent in disk blocks, which * can require more than a 32-bit field. */ nb = (size_t)(sizeof (ic_extent_block_t) + ((ebp->nextents - 1) * sizeof (ic_extent_t))); nebp = kmem_alloc(nb, KM_SLEEP); nebp->ic_nextents = ebp->nextents; nebp->ic_nbytes = ebp->nbytes; nebp->ic_nextbno = ebp->nextbno; nebp->ic_nextord = ebp->nextord; for (i = 0; i < ebp->nextents; i++) { nebp->ic_extents[i].ic_lbno = ebp->extents[i].lbno; nebp->ic_extents[i].ic_nbno = ebp->extents[i].nbno; nebp->ic_extents[i].ic_pbno = logbtodb(fs, ebp->extents[i].pbno); nebp->ic_extents[i].ic_ord = ebp->extents[i].ord; } brelse(bp); /* * Get the log state */ bno = nebp->ic_extents[0].ic_pbno; ord = nebp->ic_extents[0].ic_ord; sam_bread_db(qfsvfsp, qfsvfsp->mi.m_fs[ord].dev, bno, DEV_BSIZE, &bp); if (bp->b_flags & B_ERROR) { brelse(bp); sam_bread_db(qfsvfsp, qfsvfsp->mi.m_fs[ord].dev, bno + 1, DEV_BSIZE, &bp); if (bp->b_flags & B_ERROR) { brelse(bp); kmem_free(nebp, nb); return (EIO); } } /* * Put ondisk struct into an anonymous buffer * This buffer will contain the memory for the ml_odunit struct */ tbp = ngeteblk(dbtob(LS_SECTORS)); tbp->b_edev = bp->b_edev; tbp->b_dev = bp->b_dev; tbp->b_blkno = bno; bcopy(bp->b_un.b_addr, tbp->b_un.b_addr, DEV_BSIZE); bcopy(bp->b_un.b_addr, tbp->b_un.b_addr + DEV_BSIZE, DEV_BSIZE); bp->b_flags |= (B_STALE | B_AGE); brelse(bp); bp = tbp; /* * Verify the log state * * read/only mounts w/bad logs are allowed. umount will * eventually roll the bad log until the first IO error. * fsck will then repair the file system. * * read/write mounts with bad logs are not allowed. * */ ul = (ml_unit_t *)kmem_zalloc(sizeof (*ul), KM_SLEEP); bcopy(bp->b_un.b_addr, &ul->un_ondisk, sizeof (ml_odunit_t)); if ((ul->un_chksum != ul->un_head_ident + ul->un_tail_ident) || (ul->un_version != LQFS_VERSION_LATEST) || (!ronly && ul->un_badlog)) { kmem_free(ul, sizeof (*ul)); brelse(bp); kmem_free(nebp, nb); return (EIO); } /* * Initialize the incore-only fields */ if (ronly) { ul->un_flags |= LDL_NOROLL; } ul->un_bp = bp; ul->un_qfsvfs = qfsvfsp; ul->un_dev = qfsvfsp->mi.m_fs[ord].dev; ul->un_ebp = nebp; ul->un_nbeb = nb; ul->un_maxresv = btodb(ul->un_logsize) * LDL_USABLE_BSIZE; ul->un_deltamap = map_get(ul, deltamaptype, DELTAMAP_NHASH); ul->un_logmap = map_get(ul, logmaptype, LOGMAP_NHASH); if (ul->un_debug & MT_MATAMAP) { ul->un_matamap = map_get(ul, matamaptype, DELTAMAP_NHASH); } sam_mutex_init(&ul->un_log_mutex, NULL, MUTEX_DEFAULT, NULL); sam_mutex_init(&ul->un_state_mutex, NULL, MUTEX_DEFAULT, NULL); /* * Aquire the qfs_scan_lock before linking the mtm data * structure so that we keep qfs_sync() and qfs_update() away * when they execute the qfs_scan_inodes() run while we're in * progress of enabling/disabling logging. */ mutex_enter(&qfs_scan_lock); LQFS_SET_LOGP(qfsvfsp, ul); ml_unit_validate(ul); /* remember the state of the log before the log scan */ logmap_logscan(ul); mutex_exit(&qfs_scan_lock); /* * Error during scan * * If this is a read/only mount; ignore the error. * At a later time umount/fsck will repair the fs. * */ if (ul->un_flags & LDL_ERROR) { if (!ronly) { /* * Aquire the qfs_scan_lock before de-linking * the mtm data structure so that we keep qfs_sync() * and qfs_update() away when they execute the * qfs_scan_inodes() run while we're in progress of * enabling/disabling logging. */ mutex_enter(&qfs_scan_lock); lqfs_unsnarf(qfsvfsp); mutex_exit(&qfs_scan_lock); return (EIO); } ul->un_flags &= ~LDL_ERROR; } if (!ronly) { logmap_start_roll(ul); } return (0); }
/* * Free log space * Assumes the file system is write locked and is not logging */ int lqfs_free(qfsvfs_t *qfsvfsp) { int error = 0, i, j; buf_t *bp = NULL; extent_t *ep; extent_block_t *ebp; fs_lqfs_common_t *fs = VFS_FS_PTR(qfsvfsp); daddr_t fno; int32_t logbno; ushort_t logord; long nfno; inode_t *ip = NULL; char clean; /* * Nothing to free */ if (LQFS_GET_LOGBNO(fs) == 0) { return (0); } /* * Mark the file system as FSACTIVE and no log but honor the * current value of fs_reclaim. The reclaim thread could have * been active when lqfs_disable() was called and if fs_reclaim * is reset to zero here it could lead to lost inodes. */ UL_SBOWNER_SET(qfsvfsp, curthread); VFS_LOCK_MUTEX_ENTER(qfsvfsp); clean = LQFS_GET_FS_CLEAN(fs); logbno = LQFS_GET_LOGBNO(fs); logord = LQFS_GET_LOGORD(fs); LQFS_SET_FS_CLEAN(fs, FSACTIVE); LQFS_SET_LOGBNO(fs, INT32_C(0)); LQFS_SET_LOGORD(fs, 0); #ifdef LUFS qfs_sbwrite(qfsvfsp); error = (qfsvfsp->vfs_bufp->b_flags & B_ERROR); #else error = sam_update_sblk(qfsvfsp, 0, 0, TRUE); error = sam_update_sblk(qfsvfsp, 0, 1, TRUE); #endif /* LUFS */ VFS_LOCK_MUTEX_EXIT(qfsvfsp); UL_SBOWNER_SET(qfsvfsp, -1); if (error) { error = EIO; LQFS_SET_FS_CLEAN(fs, clean); LQFS_SET_LOGBNO(fs, logbno); LQFS_SET_LOGORD(fs, logord); goto errout; } /* * fetch the allocation block * superblock -> one block of extents -> log data */ sam_bread_db(qfsvfsp, qfsvfsp->mi.m_fs[logord].dev, logbtodb(fs, logbno), FS_BSIZE(fs), &bp); if (bp->b_flags & B_ERROR) { error = EIO; goto errout; } #ifdef LUFS /* * Free up the allocated space (dummy inode needed for free()) */ ip = qfs_alloc_inode(qfsvfsp, QFSROOTINO); #else /* * QFS doesn't need an inode to free blocks. */ #endif /* LUFS */ ebp = (void *)bp->b_un.b_addr; for (i = 0, ep = &ebp->extents[0]; i < ebp->nextents; ++i, ++ep) { fno = logbtofrag(fs, ep->pbno); nfno = dbtofsb(fs, ep->nbno); for (j = 0; j < nfno; j += FS_FRAG(fs), fno += FS_FRAG(fs)) { #ifdef LUFS free(ip, fno, FS_BSIZE(fs), 0); #else sam_free_block(qfsvfsp, SM, logbtofsblk(fs, fno), ep->ord); #endif /* LUFS */ } } #ifdef LUFS free(ip, logbtofrag(fs, logbno), FS_BSIZE(fs), 0); #else sam_free_block(qfsvfsp, SM, logbtofsblk(fs, logbno), logord); #endif /* LUFS */ brelse(bp); bp = NULL; /* * Push the metadata dirtied during the allocations */ UL_SBOWNER_SET(qfsvfsp, curthread); #ifdef LUFS sbupdate(qfsvfsp->vfs_vfs); #else sam_update_sblk(qfsvfsp, 0, 0, TRUE); #endif /* LUFS */ UL_SBOWNER_SET(qfsvfsp, -1); bflush(qfsvfsp->mi.m_fs[logord].dev); error = bfinval(qfsvfsp->mi.m_fs[logord].dev, 0); if (error) { goto errout; } /* * Free the dummy inode */ #ifdef LUFS qfs_free_inode(ip); #else /* QFS uses a reserved inode */ VN_RELE(SAM_ITOV(ip)); #endif /* LUFS */ return (0); errout: /* * Free up all resources */ if (bp) { brelse(bp); } if (ip) { #ifdef LUFS qfs_free_inode(ip); #else /* QFS uses a reserved inode */ VN_RELE(SAM_ITOV(ip)); #endif /* LUFS */ } return (error); }
/* ARGSUSED */ static int lqfs_log_validate(qfsvfs_t *qfsvfsp, struct fiolog *flp, cred_t *cr) { int error = 0; buf_t *bp = NULL; extent_t *ep; extent_block_t *ebp; fs_lqfs_common_t *fs = VFS_FS_PTR(qfsvfsp); daddr_t fno; /* in frags */ #ifdef LUFS extent_t *nep; daddr_t bno; /* in disk blocks */ #endif /* LUFS */ int32_t logbno; int logord; int i; int j; long nfno; logbno = LQFS_GET_LOGBNO(fs); logord = LQFS_GET_LOGORD(fs); if (logbno == 0) { error = EINVAL; goto errout; } LQFS_MSG(CE_WARN, "lqfs_log_validate: Extent alloc block offset 0x%x ord %d.\n", (dbtob(logbtodb(fs, logbno))), logord); sam_bread_db(qfsvfsp, qfsvfsp->mi.m_fs[logord].dev, logbtodb(fs, logbno), FS_BSIZE(fs), &bp); if (bp->b_flags & B_ERROR) { LQFS_MSG(CE_WARN, "lqfs_log_validate: Can't read extent alloc block\n"); error = EIO; goto errout; } ebp = (void *)bp->b_un.b_addr; LQFS_MSG(CE_WARN, "lqfs_log_validate: Ext alloc block type 0x%x chksum 0x%x\n", ebp->type, ebp->chksum); LQFS_MSG(CE_WARN, "lqfs_log_validate: Ext alloc block nextents 0x%x nb 0x%x.\n", ebp->nextents, ebp->nbytes); LQFS_MSG(CE_WARN, "lqfs_log_validate: Ext alloc block nxtbno 0x%x nxtord 0x%x.\n", ebp->nextbno, ebp->nextord); for (i = 0, ep = &ebp->extents[0]; i < ebp->nextents; ++i, ++ep) { fno = logbtofrag(fs, ep->pbno); nfno = dbtofsb(fs, ep->nbno); LQFS_MSG(CE_WARN, " Extent # %d - 0x%x 1K blocks:\n", i, nfno); for (j = 0; j < nfno; j += FS_FRAG(fs), fno += FS_FRAG(fs)) { int lastord; if (j == 0) { LQFS_MSG(CE_WARN, " First 4K block at offset 0x%x " "ord %d (incl. last 1K frag 0x%x, last " "sector 0x%x)\n", logbtofsblk(fs, fno), ep->ord, fno+FS_FRAG(fs)-1, logbtodb(fs, fno+1)-1); lastord = ep->ord; } else if (j >= (nfno - (FS_FRAG(fs)))) { LQFS_MSG(CE_WARN, " Last 4K block at offset 0x%x " "ord %d (incl. last 1K frag 0x%x, last " "sector 0x%x)\n", logbtofsblk(fs, fno), ep->ord, fno+FS_FRAG(fs)-1, logbtodb(fs, fno+1)-1); } else if (ep->ord != lastord) { LQFS_MSG(CE_WARN, " Includes 4K block at offset " "0x%x ord %d (incl. last 1K frag 0x%x, " "last sector 0x%x)\n", logbtofsblk(fs, fno), ep->ord, fno+FS_FRAG(fs)-1, logbtodb(fs, fno+1)-1); lastord = ep->ord; } } } errout: if (bp) { brelse(bp); } if (!error) { LQFS_MSG(CE_WARN, "lqfs_log_validate(): Returning OK.\n"); } else { LQFS_MSG(CE_WARN, "lqfs_log_validate(): Returning error code %d\n", error); } return (error); }