/* * Interface of geteblk() is kept intact to maintain driver compatibility. * Use ngeteblk() to allocate block size other than 1 KB. */ struct buf * geteblk(void) { return (ngeteblk((long)1024)); }
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); }