diff options
author | Dave Chinner <dchinner@redhat.com> | 2015-08-19 03:31:54 +0300 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2015-08-19 03:31:54 +0300 |
commit | fcfbe2c4ef4243cc11a1cd64ee1b4907b6afea06 (patch) | |
tree | 8f96db333c8177d7c933725e83dcd71f9e7f3012 /fs/xfs/xfs_log_recover.c | |
parent | ac383de20d468a75e7023caf06dcf6606cd85220 (diff) | |
download | linux-fcfbe2c4ef4243cc11a1cd64ee1b4907b6afea06.tar.xz |
xfs: log recovery needs to validate against sb_meta_uuid
Now that sb_uuid can be changed by the user, we cannot use this to
validate the metadata blocks being recovered belong to this
filesystem. We must check against the sb_meta_uuid as that will
remain unchanged.
There is a complication in this code - the superblock itself. We can
not check the sb_meta_uuid unconditionally, as that may not be set
on disk. Hence we must verify the superblock sb_uuid matches between
the log record and the in-core superblock.
Found by inspection after the previous two problems were found.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs/xfs_log_recover.c')
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 01dd228ca05e..86c3de477a9d 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -1890,15 +1890,25 @@ xlog_recover_get_buf_lsn( uuid = &((struct xfs_attr3_rmt_hdr *)blk)->rm_uuid; break; case XFS_SB_MAGIC: + /* + * superblock uuids are magic. We may or may not have a + * sb_meta_uuid on disk, but it will be set in the in-core + * superblock. We set the uuid pointer for verification + * according to the superblock feature mask to ensure we check + * the relevant UUID in the superblock. + */ lsn = be64_to_cpu(((struct xfs_dsb *)blk)->sb_lsn); - uuid = &((struct xfs_dsb *)blk)->sb_uuid; + if (xfs_sb_version_hasmetauuid(&mp->m_sb)) + uuid = &((struct xfs_dsb *)blk)->sb_meta_uuid; + else + uuid = &((struct xfs_dsb *)blk)->sb_uuid; break; default: break; } if (lsn != (xfs_lsn_t)-1) { - if (!uuid_equal(&mp->m_sb.sb_uuid, uuid)) + if (!uuid_equal(&mp->m_sb.sb_meta_uuid, uuid)) goto recover_immediately; return lsn; } |