xfs_log.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,167 行 · 第 1/5 页
C
2,167 行
} return retval;} /* xfs_log_reserve *//* * Mount a log filesystem * * mp - ubiquitous xfs mount point structure * log_target - buftarg of on-disk log device * blk_offset - Start block # where block size is 512 bytes (BBSIZE) * num_bblocks - Number of BBSIZE blocks in on-disk log * * Return error or zero. */intxfs_log_mount(xfs_mount_t *mp, xfs_buftarg_t *log_target, xfs_daddr_t blk_offset, int num_bblks){ if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) cmn_err(CE_NOTE, "XFS mounting filesystem %s", mp->m_fsname); else { cmn_err(CE_NOTE, "!Mounting filesystem \"%s\" in no-recovery mode. Filesystem will be inconsistent.", mp->m_fsname); ASSERT(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY); } mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks);#if defined(DEBUG) || defined(XLOG_NOLOG) if (!xlog_debug) { cmn_err(CE_NOTE, "log dev: %s", XFS_BUFTARG_NAME(log_target)); return 0; }#endif /* * skip log recovery on a norecovery mount. pretend it all * just worked. */ if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) { int error; vfs_t *vfsp = XFS_MTOVFS(mp); int readonly = (vfsp->vfs_flag & VFS_RDONLY); if (readonly) vfsp->vfs_flag &= ~VFS_RDONLY; error = xlog_recover(mp->m_log, readonly); if (readonly) vfsp->vfs_flag |= VFS_RDONLY; if (error) { cmn_err(CE_WARN, "XFS: log mount/recovery failed: error %d", error); xlog_unalloc_log(mp->m_log); return error; } } /* Normal transactions can now occur */ mp->m_log->l_flags &= ~XLOG_ACTIVE_RECOVERY; /* End mounting message in xfs_log_mount_finish */ return 0;} /* xfs_log_mount *//* * Finish the recovery of the file system. This is separate from * the xfs_log_mount() call, because it depends on the code in * xfs_mountfs() to read in the root and real-time bitmap inodes * between calling xfs_log_mount() and here. * * mp - ubiquitous xfs mount point structure */intxfs_log_mount_finish(xfs_mount_t *mp, int mfsi_flags){ int error; if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) error = xlog_recover_finish(mp->m_log, mfsi_flags); else { error = 0; ASSERT(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY); } return error;}/* * Unmount processing for the log. */intxfs_log_unmount(xfs_mount_t *mp){ int error; error = xfs_log_unmount_write(mp); xfs_log_unmount_dealloc(mp); return (error);}/* * Final log writes as part of unmount. * * Mark the filesystem clean as unmount happens. Note that during relocation * this routine needs to be executed as part of source-bag while the * deallocation must not be done until source-end. *//* * Unmount record used to have a string "Unmount filesystem--" in the * data section where the "Un" was really a magic number (XLOG_UNMOUNT_TYPE). * We just write the magic number now since that particular field isn't * currently architecture converted and "nUmount" is a bit foo. * As far as I know, there weren't any dependencies on the old behaviour. */intxfs_log_unmount_write(xfs_mount_t *mp){ xlog_t *log = mp->m_log; xlog_in_core_t *iclog;#ifdef DEBUG xlog_in_core_t *first_iclog;#endif xfs_log_iovec_t reg[1]; xfs_log_ticket_t tic = NULL; xfs_lsn_t lsn; int error; SPLDECL(s); /* the data section must be 32 bit size aligned */ struct { __uint16_t magic; __uint16_t pad1; __uint32_t pad2; /* may as well make it 64 bits */ } magic = { XLOG_UNMOUNT_TYPE, 0, 0 };#if defined(DEBUG) || defined(XLOG_NOLOG) if (!xlog_debug && xlog_target == log->l_targ) return 0;#endif /* * Don't write out unmount record on read-only mounts. * Or, if we are doing a forced umount (typically because of IO errors). */ if (XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY) return 0; xfs_log_force(mp, 0, XFS_LOG_FORCE|XFS_LOG_SYNC);#ifdef DEBUG first_iclog = iclog = log->l_iclog; do { if (!(iclog->ic_state & XLOG_STATE_IOERROR)) { ASSERT(iclog->ic_state & XLOG_STATE_ACTIVE); ASSERT(iclog->ic_offset == 0); } iclog = iclog->ic_next; } while (iclog != first_iclog);#endif if (! (XLOG_FORCED_SHUTDOWN(log))) { reg[0].i_addr = (void*)&magic; reg[0].i_len = sizeof(magic); error = xfs_log_reserve(mp, 600, 1, &tic, XFS_LOG, 0); if (!error) { /* remove inited flag */ ((xlog_ticket_t *)tic)->t_flags = 0; error = xlog_write(mp, reg, 1, tic, &lsn, NULL, XLOG_UNMOUNT_TRANS); /* * At this point, we're umounting anyway, * so there's no point in transitioning log state * to IOERROR. Just continue... */ } if (error) { xfs_fs_cmn_err(CE_ALERT, mp, "xfs_log_unmount: unmount record failed"); } s = LOG_LOCK(log); iclog = log->l_iclog; iclog->ic_refcnt++; LOG_UNLOCK(log, s); xlog_state_want_sync(log, iclog); (void) xlog_state_release_iclog(log, iclog); s = LOG_LOCK(log); if (!(iclog->ic_state == XLOG_STATE_ACTIVE || iclog->ic_state == XLOG_STATE_DIRTY)) { if (!XLOG_FORCED_SHUTDOWN(log)) { sv_wait(&iclog->ic_forcesema, PMEM, &log->l_icloglock, s); } else { LOG_UNLOCK(log, s); } } else { LOG_UNLOCK(log, s); } if (tic) xlog_state_put_ticket(log, tic); } else { /* * We're already in forced_shutdown mode, couldn't * even attempt to write out the unmount transaction. * * Go through the motions of sync'ing and releasing * the iclog, even though no I/O will actually happen, * we need to wait for other log I/O's that may already * be in progress. Do this as a separate section of * code so we'll know if we ever get stuck here that * we're in this odd situation of trying to unmount * a file system that went into forced_shutdown as * the result of an unmount.. */ s = LOG_LOCK(log); iclog = log->l_iclog; iclog->ic_refcnt++; LOG_UNLOCK(log, s); xlog_state_want_sync(log, iclog); (void) xlog_state_release_iclog(log, iclog); s = LOG_LOCK(log); if ( ! ( iclog->ic_state == XLOG_STATE_ACTIVE || iclog->ic_state == XLOG_STATE_DIRTY || iclog->ic_state == XLOG_STATE_IOERROR) ) { sv_wait(&iclog->ic_forcesema, PMEM, &log->l_icloglock, s); } else { LOG_UNLOCK(log, s); } } return 0;} /* xfs_log_unmount_write *//* * Deallocate log structures for unmount/relocation. */voidxfs_log_unmount_dealloc(xfs_mount_t *mp){ xlog_unalloc_log(mp->m_log);}/* * Write region vectors to log. The write happens using the space reservation * of the ticket (tic). It is not a requirement that all writes for a given * transaction occur with one call to xfs_log_write(). */intxfs_log_write(xfs_mount_t * mp, xfs_log_iovec_t reg[], int nentries, xfs_log_ticket_t tic, xfs_lsn_t *start_lsn){ int error; xlog_t *log = mp->m_log;#if defined(DEBUG) || defined(XLOG_NOLOG) if (!xlog_debug && xlog_target == log->l_targ) { *start_lsn = 0; return 0; }#endif if (XLOG_FORCED_SHUTDOWN(log)) return XFS_ERROR(EIO); if ((error = xlog_write(mp, reg, nentries, tic, start_lsn, NULL, 0))) { xfs_force_shutdown(mp, XFS_LOG_IO_ERROR); } return (error);} /* xfs_log_write */voidxfs_log_move_tail(xfs_mount_t *mp, xfs_lsn_t tail_lsn){ xlog_ticket_t *tic; xlog_t *log = mp->m_log; int need_bytes, free_bytes, cycle, bytes; SPLDECL(s);#if defined(DEBUG) || defined(XLOG_NOLOG) if (!xlog_debug && xlog_target == log->l_targ) return;#endif /* XXXsup tmp */ if (XLOG_FORCED_SHUTDOWN(log)) return; ASSERT(!XFS_FORCED_SHUTDOWN(mp)); if (tail_lsn == 0) { /* needed since sync_lsn is 64 bits */ s = LOG_LOCK(log); tail_lsn = log->l_last_sync_lsn; LOG_UNLOCK(log, s); } s = GRANT_LOCK(log); /* Also an invalid lsn. 1 implies that we aren't passing in a valid * tail_lsn. */ if (tail_lsn != 1) { log->l_tail_lsn = tail_lsn; } if ((tic = log->l_write_headq)) {#ifdef DEBUG if (log->l_flags & XLOG_ACTIVE_RECOVERY) panic("Recovery problem");#endif cycle = log->l_grant_write_cycle; bytes = log->l_grant_write_bytes; free_bytes = xlog_space_left(log, cycle, bytes); do { ASSERT(tic->t_flags & XLOG_TIC_PERM_RESERV); if (free_bytes < tic->t_unit_res && tail_lsn != 1) break; tail_lsn = 0; free_bytes -= tic->t_unit_res; sv_signal(&tic->t_sema); tic = tic->t_next; } while (tic != log->l_write_headq); } if ((tic = log->l_reserve_headq)) {#ifdef DEBUG if (log->l_flags & XLOG_ACTIVE_RECOVERY) panic("Recovery problem");#endif cycle = log->l_grant_reserve_cycle; bytes = log->l_grant_reserve_bytes; free_bytes = xlog_space_left(log, cycle, bytes); do { if (tic->t_flags & XLOG_TIC_PERM_RESERV) need_bytes = tic->t_unit_res*tic->t_cnt; else need_bytes = tic->t_unit_res; if (free_bytes < need_bytes && tail_lsn != 1) break; tail_lsn = 0; free_bytes -= need_bytes; sv_signal(&tic->t_sema); tic = tic->t_next; } while (tic != log->l_reserve_headq); } GRANT_UNLOCK(log, s);} /* xfs_log_move_tail *//* * Determine if we have a transaction that has gone to disk * that needs to be covered. Log activity needs to be idle (no AIL and * nothing in the iclogs). And, we need to be in the right state indicating * something has gone out. */intxfs_log_need_covered(xfs_mount_t *mp){ SPLDECL(s); int needed = 0, gen; xlog_t *log = mp->m_log; vfs_t *vfsp = XFS_MTOVFS(mp); if (fs_frozen(vfsp) || XFS_FORCED_SHUTDOWN(mp) || (vfsp->vfs_flag & VFS_RDONLY)) return 0; s = LOG_LOCK(log); if (((log->l_covered_state == XLOG_STATE_COVER_NEED) || (log->l_covered_state == XLOG_STATE_COVER_NEED2)) && !xfs_trans_first_ail(mp, &gen) && xlog_iclogs_empty(log)) { if (log->l_covered_state == XLOG_STATE_COVER_NEED) log->l_covered_state = XLOG_STATE_COVER_DONE; else { ASSERT(log->l_covered_state == XLOG_STATE_COVER_NEED2); log->l_covered_state = XLOG_STATE_COVER_DONE2; } needed = 1; } LOG_UNLOCK(log, s); return(needed);}/****************************************************************************** * * local routines * ****************************************************************************** *//* xfs_trans_tail_ail returns 0 when there is nothing in the list. * The log manager must keep track of the last LR which was committed * to disk. The lsn of this LR will become the new tail_lsn whenever * xfs_trans_tail_ail returns 0. If we don't do this, we run into * the situation where stuff could be written into the log but nothing * was ever in the AIL when asked. Eventually, we panic since the * tail hits the head. * * We may be holding the log iclog lock upon entering this routine. */xfs_lsn_txlog_assign_tail_lsn(xfs_mount_t *mp){ xfs_lsn_t tail_lsn; SPLDECL(s); xlog_t *log = mp->m_log; tail_lsn = xfs_trans_tail_ail(mp); s = GRANT_LOCK(log); if (tail_lsn != 0) { log->l_tail_lsn = tail_lsn; } else { tail_lsn = log->l_tail_lsn = log->l_last_sync_lsn; } GRANT_UNLOCK(log, s); return tail_lsn;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?