diff options
| -rw-r--r-- | fs/xfs/libxfs/xfs_attr_remote.c | 29 | ||||
| -rw-r--r-- | fs/xfs/xfs_log_recover.c | 11 |
2 files changed, 31 insertions, 9 deletions
diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c index 20de88d1bf86..2faec26962e8 100644 --- a/fs/xfs/libxfs/xfs_attr_remote.c +++ b/fs/xfs/libxfs/xfs_attr_remote.c | |||
| @@ -159,11 +159,10 @@ xfs_attr3_rmt_write_verify( | |||
| 159 | struct xfs_buf *bp) | 159 | struct xfs_buf *bp) |
| 160 | { | 160 | { |
| 161 | struct xfs_mount *mp = bp->b_target->bt_mount; | 161 | struct xfs_mount *mp = bp->b_target->bt_mount; |
| 162 | struct xfs_buf_log_item *bip = bp->b_fspriv; | 162 | int blksize = mp->m_attr_geo->blksize; |
| 163 | char *ptr; | 163 | char *ptr; |
| 164 | int len; | 164 | int len; |
| 165 | xfs_daddr_t bno; | 165 | xfs_daddr_t bno; |
| 166 | int blksize = mp->m_attr_geo->blksize; | ||
| 167 | 166 | ||
| 168 | /* no verification of non-crc buffers */ | 167 | /* no verification of non-crc buffers */ |
| 169 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | 168 | if (!xfs_sb_version_hascrc(&mp->m_sb)) |
| @@ -175,16 +174,22 @@ xfs_attr3_rmt_write_verify( | |||
| 175 | ASSERT(len >= blksize); | 174 | ASSERT(len >= blksize); |
| 176 | 175 | ||
| 177 | while (len > 0) { | 176 | while (len > 0) { |
| 177 | struct xfs_attr3_rmt_hdr *rmt = (struct xfs_attr3_rmt_hdr *)ptr; | ||
| 178 | |||
| 178 | if (!xfs_attr3_rmt_verify(mp, ptr, blksize, bno)) { | 179 | if (!xfs_attr3_rmt_verify(mp, ptr, blksize, bno)) { |
| 179 | xfs_buf_ioerror(bp, -EFSCORRUPTED); | 180 | xfs_buf_ioerror(bp, -EFSCORRUPTED); |
| 180 | xfs_verifier_error(bp); | 181 | xfs_verifier_error(bp); |
| 181 | return; | 182 | return; |
| 182 | } | 183 | } |
| 183 | if (bip) { | ||
| 184 | struct xfs_attr3_rmt_hdr *rmt; | ||
| 185 | 184 | ||
| 186 | rmt = (struct xfs_attr3_rmt_hdr *)ptr; | 185 | /* |
| 187 | rmt->rm_lsn = cpu_to_be64(bip->bli_item.li_lsn); | 186 | * Ensure we aren't writing bogus LSNs to disk. See |
| 187 | * xfs_attr3_rmt_hdr_set() for the explanation. | ||
| 188 | */ | ||
| 189 | if (rmt->rm_lsn != cpu_to_be64(NULLCOMMITLSN)) { | ||
| 190 | xfs_buf_ioerror(bp, -EFSCORRUPTED); | ||
| 191 | xfs_verifier_error(bp); | ||
| 192 | return; | ||
| 188 | } | 193 | } |
| 189 | xfs_update_cksum(ptr, blksize, XFS_ATTR3_RMT_CRC_OFF); | 194 | xfs_update_cksum(ptr, blksize, XFS_ATTR3_RMT_CRC_OFF); |
| 190 | 195 | ||
| @@ -221,6 +226,18 @@ xfs_attr3_rmt_hdr_set( | |||
| 221 | rmt->rm_owner = cpu_to_be64(ino); | 226 | rmt->rm_owner = cpu_to_be64(ino); |
| 222 | rmt->rm_blkno = cpu_to_be64(bno); | 227 | rmt->rm_blkno = cpu_to_be64(bno); |
| 223 | 228 | ||
| 229 | /* | ||
| 230 | * Remote attribute blocks are written synchronously, so we don't | ||
| 231 | * have an LSN that we can stamp in them that makes any sense to log | ||
| 232 | * recovery. To ensure that log recovery handles overwrites of these | ||
| 233 | * blocks sanely (i.e. once they've been freed and reallocated as some | ||
| 234 | * other type of metadata) we need to ensure that the LSN has a value | ||
| 235 | * that tells log recovery to ignore the LSN and overwrite the buffer | ||
| 236 | * with whatever is in it's log. To do this, we use the magic | ||
| 237 | * NULLCOMMITLSN to indicate that the LSN is invalid. | ||
| 238 | */ | ||
| 239 | rmt->rm_lsn = cpu_to_be64(NULLCOMMITLSN); | ||
| 240 | |||
| 224 | return sizeof(struct xfs_attr3_rmt_hdr); | 241 | return sizeof(struct xfs_attr3_rmt_hdr); |
| 225 | } | 242 | } |
| 226 | 243 | ||
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 01dd228ca05e..480ebba8464f 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
| @@ -1886,9 +1886,14 @@ xlog_recover_get_buf_lsn( | |||
| 1886 | uuid = &((struct xfs_dir3_blk_hdr *)blk)->uuid; | 1886 | uuid = &((struct xfs_dir3_blk_hdr *)blk)->uuid; |
| 1887 | break; | 1887 | break; |
| 1888 | case XFS_ATTR3_RMT_MAGIC: | 1888 | case XFS_ATTR3_RMT_MAGIC: |
| 1889 | lsn = be64_to_cpu(((struct xfs_attr3_rmt_hdr *)blk)->rm_lsn); | 1889 | /* |
| 1890 | uuid = &((struct xfs_attr3_rmt_hdr *)blk)->rm_uuid; | 1890 | * Remote attr blocks are written synchronously, rather than |
| 1891 | break; | 1891 | * being logged. That means they do not contain a valid LSN |
| 1892 | * (i.e. transactionally ordered) in them, and hence any time we | ||
| 1893 | * see a buffer to replay over the top of a remote attribute | ||
| 1894 | * block we should simply do so. | ||
| 1895 | */ | ||
| 1896 | goto recover_immediately; | ||
| 1892 | case XFS_SB_MAGIC: | 1897 | case XFS_SB_MAGIC: |
| 1893 | lsn = be64_to_cpu(((struct xfs_dsb *)blk)->sb_lsn); | 1898 | lsn = be64_to_cpu(((struct xfs_dsb *)blk)->sb_lsn); |
| 1894 | uuid = &((struct xfs_dsb *)blk)->sb_uuid; | 1899 | uuid = &((struct xfs_dsb *)blk)->sb_uuid; |
