if (XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) ||
(rec->rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))) { /* Continue the query because this isn't a failure. */ if (notify->mf_flags & MF_MEM_PRE_REMOVE) return 0;
notify->want_shutdown = true; return 0;
}
/* Get files that incore, filter out others that are not in use. */
error = xfs_iget(mp, cur->bc_tp, rec->rm_owner, XFS_IGET_INCORE,
0, &ip); /* Continue the rmap query if the inode isn't incore */ if (error == -ENODATA) return 0; if (error) {
notify->want_shutdown = true; return 0;
}
/* Continue the rmap query if the inode isn't a dax file. */ if (dax_mapping(mapping))
error = mf_dax_kill_procs(mapping, pgoff, pgcnt,
notify->mf_flags);
/* Invalidate the cache in dax pages. */ if (notify->mf_flags & MF_MEM_PRE_REMOVE)
invalidate_inode_pages2_range(mapping, pgoff,
pgoff + pgcnt - 1);
/* Notify failure on the whole device. */ if (offset == 0 && len == U64_MAX) {
offset = dev_start;
len = dev_len;
}
/* Ignore the range out of filesystem area */ if (offset + len - 1 < dev_start) return -ENXIO; if (offset > dev_end) return -ENXIO;
/* Calculate the real range when it touches the boundary */ if (offset > dev_start)
offset -= dev_start; else {
len -= dev_start - offset;
offset = 0;
} if (offset + len - 1 > dev_end)
len = dev_end - offset + 1;
staticint
xfs_dax_notify_logdev_failure( struct xfs_mount *mp,
u64 offset,
u64 len, int mf_flags)
{
xfs_daddr_t daddr;
uint64_t bblen; int error;
/* * Return ENXIO instead of shutting down the filesystem if the failed * region is beyond the end of the log.
*/
error = xfs_dax_translate_range(mp->m_logdev_targp,
offset, len, &daddr, &bblen); if (error) return error;
/* * In the pre-remove case the failure notification is attempting to * trigger a force unmount. The expectation is that the device is * still present, but its removal is in progress and can not be * cancelled, proceed with accessing the log device.
*/ if (mf_flags & MF_MEM_PRE_REMOVE) return 0;
if (mf_flags & MF_MEM_PRE_REMOVE) {
xfs_info(mp, "Device is about to be removed!"); /* * Freeze fs to prevent new mappings from being created. * - Keep going on if others already hold the kernel forzen. * - Keep going on if other errors too because this device is * starting to fail. * - If kernel frozen state is hold successfully here, thaw it * here as well at the end.
*/
kernel_frozen = xfs_dax_notify_failure_freeze(mp) == 0;
}
cur = xfs_rmapbt_init_cursor(mp, tp, agf_bp, pag);
} else {
rtg = to_rtg(xg);
xfs_rtgroup_lock(rtg, XFS_RTGLOCK_RMAP);
cur = xfs_rtrmapbt_init_cursor(tp, rtg);
}
/* * Set the rmap range from ri_low to ri_high, which represents * a [start, end] where we looking for the files or metadata.
*/
memset(&ri_high, 0xFF, sizeof(ri_high)); if (xg->xg_gno == start_gno)
ri_low.rm_startblock =
xfs_fsb_to_gbno(mp, start_bno, type); if (xg->xg_gno == end_gno)
ri_high.rm_startblock =
xfs_fsb_to_gbno(mp, end_bno, type);
error = xfs_rmap_query_range(cur, &ri_low, &ri_high,
xfs_dax_failure_fn, ¬ify);
xfs_btree_del_cursor(cur, error); if (agf_bp)
xfs_trans_brelse(tp, agf_bp); if (rtg)
xfs_rtgroup_unlock(rtg, XFS_RTGLOCK_RMAP); if (error) {
xfs_group_put(xg); break;
}
}
xfs_trans_cancel(tp);
/* * Shutdown fs from a force umount in pre-remove case which won't fail, * so errors can be ignored. Otherwise, shutdown the filesystem with * CORRUPT flag if error occured or notify.want_shutdown was set during * RMAP querying.
*/ if (mf_flags & MF_MEM_PRE_REMOVE)
xfs_force_shutdown(mp, SHUTDOWN_FORCE_UMOUNT); elseif (error || notify.want_shutdown) {
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_ONDISK); if (!error)
error = -EFSCORRUPTED;
}
/* Thaw the fs if it has been frozen before. */ if (mf_flags & MF_MEM_PRE_REMOVE)
xfs_dax_notify_failure_thaw(mp, kernel_frozen);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.