Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xfs: create new metadata UUID field and incompat flag

This adds a new superblock field, sb_meta_uuid. If set, along with
a new incompat flag, the code will use that field on a V5 filesystem
to compare to metadata UUIDs, which allows us to change the user-
visible UUID at will. Userspace handles the setting and clearing
of the incompat flag as appropriate, as the UUID gets changed; i.e.
setting the user-visible UUID back to the original UUID (as stored in
the new field) will remove the incompatible feature flag.

If the incompat flag is not set, this copies the user-visible UUID into
into the meta_uuid slot in memory when the superblock is read from disk;
the meta_uuid field is not written back to disk in this case.

The remainder of this patch simply switches verifiers, initializers,
etc to use the new sb_meta_uuid field.

Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>


authored by

Eric Sandeen and committed by
Dave Chinner
ce748eaa bc0195aa

+66 -36
+2 -2
fs/xfs/libxfs/xfs_alloc.c
··· 464 464 struct xfs_agfl *agfl = XFS_BUF_TO_AGFL(bp); 465 465 int i; 466 466 467 - if (!uuid_equal(&agfl->agfl_uuid, &mp->m_sb.sb_uuid)) 467 + if (!uuid_equal(&agfl->agfl_uuid, &mp->m_sb.sb_meta_uuid)) 468 468 return false; 469 469 if (be32_to_cpu(agfl->agfl_magicnum) != XFS_AGFL_MAGIC) 470 470 return false; ··· 2260 2260 struct xfs_agf *agf = XFS_BUF_TO_AGF(bp); 2261 2261 2262 2262 if (xfs_sb_version_hascrc(&mp->m_sb) && 2263 - !uuid_equal(&agf->agf_uuid, &mp->m_sb.sb_uuid)) 2263 + !uuid_equal(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid)) 2264 2264 return false; 2265 2265 2266 2266 if (!(agf->agf_magicnum == cpu_to_be32(XFS_AGF_MAGIC) &&
+2 -2
fs/xfs/libxfs/xfs_alloc_btree.c
··· 295 295 case cpu_to_be32(XFS_ABTB_CRC_MAGIC): 296 296 if (!xfs_sb_version_hascrc(&mp->m_sb)) 297 297 return false; 298 - if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid)) 298 + if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_meta_uuid)) 299 299 return false; 300 300 if (block->bb_u.s.bb_blkno != cpu_to_be64(bp->b_bn)) 301 301 return false; ··· 313 313 case cpu_to_be32(XFS_ABTC_CRC_MAGIC): 314 314 if (!xfs_sb_version_hascrc(&mp->m_sb)) 315 315 return false; 316 - if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid)) 316 + if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_meta_uuid)) 317 317 return false; 318 318 if (block->bb_u.s.bb_blkno != cpu_to_be64(bp->b_bn)) 319 319 return false;
+2 -2
fs/xfs/libxfs/xfs_attr_leaf.c
··· 262 262 if (ichdr.magic != XFS_ATTR3_LEAF_MAGIC) 263 263 return false; 264 264 265 - if (!uuid_equal(&hdr3->info.uuid, &mp->m_sb.sb_uuid)) 265 + if (!uuid_equal(&hdr3->info.uuid, &mp->m_sb.sb_meta_uuid)) 266 266 return false; 267 267 if (be64_to_cpu(hdr3->info.blkno) != bp->b_bn) 268 268 return false; ··· 1056 1056 1057 1057 hdr3->blkno = cpu_to_be64(bp->b_bn); 1058 1058 hdr3->owner = cpu_to_be64(dp->i_ino); 1059 - uuid_copy(&hdr3->uuid, &mp->m_sb.sb_uuid); 1059 + uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid); 1060 1060 1061 1061 ichdr.freemap[0].base = sizeof(struct xfs_attr3_leaf_hdr); 1062 1062 } else {
+2 -2
fs/xfs/libxfs/xfs_attr_remote.c
··· 100 100 return false; 101 101 if (rmt->rm_magic != cpu_to_be32(XFS_ATTR3_RMT_MAGIC)) 102 102 return false; 103 - if (!uuid_equal(&rmt->rm_uuid, &mp->m_sb.sb_uuid)) 103 + if (!uuid_equal(&rmt->rm_uuid, &mp->m_sb.sb_meta_uuid)) 104 104 return false; 105 105 if (be64_to_cpu(rmt->rm_blkno) != bno) 106 106 return false; ··· 217 217 rmt->rm_magic = cpu_to_be32(XFS_ATTR3_RMT_MAGIC); 218 218 rmt->rm_offset = cpu_to_be32(offset); 219 219 rmt->rm_bytes = cpu_to_be32(size); 220 - uuid_copy(&rmt->rm_uuid, &mp->m_sb.sb_uuid); 220 + uuid_copy(&rmt->rm_uuid, &mp->m_sb.sb_meta_uuid); 221 221 rmt->rm_owner = cpu_to_be64(ino); 222 222 rmt->rm_blkno = cpu_to_be64(bno); 223 223
+3 -2
fs/xfs/libxfs/xfs_bmap_btree.c
··· 349 349 350 350 if (xfs_sb_version_hascrc(&mp->m_sb)) { 351 351 ASSERT(rblock->bb_magic == cpu_to_be32(XFS_BMAP_CRC_MAGIC)); 352 - ASSERT(uuid_equal(&rblock->bb_u.l.bb_uuid, &mp->m_sb.sb_uuid)); 352 + ASSERT(uuid_equal(&rblock->bb_u.l.bb_uuid, 353 + &mp->m_sb.sb_meta_uuid)); 353 354 ASSERT(rblock->bb_u.l.bb_blkno == 354 355 cpu_to_be64(XFS_BUF_DADDR_NULL)); 355 356 } else ··· 648 647 case cpu_to_be32(XFS_BMAP_CRC_MAGIC): 649 648 if (!xfs_sb_version_hascrc(&mp->m_sb)) 650 649 return false; 651 - if (!uuid_equal(&block->bb_u.l.bb_uuid, &mp->m_sb.sb_uuid)) 650 + if (!uuid_equal(&block->bb_u.l.bb_uuid, &mp->m_sb.sb_meta_uuid)) 652 651 return false; 653 652 if (be64_to_cpu(block->bb_u.l.bb_blkno) != bp->b_bn) 654 653 return false;
+6 -4
fs/xfs/libxfs/xfs_btree.c
··· 65 65 66 66 if (xfs_sb_version_hascrc(&mp->m_sb)) { 67 67 lblock_ok = lblock_ok && 68 - uuid_equal(&block->bb_u.l.bb_uuid, &mp->m_sb.sb_uuid) && 68 + uuid_equal(&block->bb_u.l.bb_uuid, 69 + &mp->m_sb.sb_meta_uuid) && 69 70 block->bb_u.l.bb_blkno == cpu_to_be64( 70 71 bp ? bp->b_bn : XFS_BUF_DADDR_NULL); 71 72 } ··· 116 115 117 116 if (xfs_sb_version_hascrc(&mp->m_sb)) { 118 117 sblock_ok = sblock_ok && 119 - uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid) && 118 + uuid_equal(&block->bb_u.s.bb_uuid, 119 + &mp->m_sb.sb_meta_uuid) && 120 120 block->bb_u.s.bb_blkno == cpu_to_be64( 121 121 bp ? bp->b_bn : XFS_BUF_DADDR_NULL); 122 122 } ··· 1002 1000 if (flags & XFS_BTREE_CRC_BLOCKS) { 1003 1001 buf->bb_u.l.bb_blkno = cpu_to_be64(blkno); 1004 1002 buf->bb_u.l.bb_owner = cpu_to_be64(owner); 1005 - uuid_copy(&buf->bb_u.l.bb_uuid, &mp->m_sb.sb_uuid); 1003 + uuid_copy(&buf->bb_u.l.bb_uuid, &mp->m_sb.sb_meta_uuid); 1006 1004 buf->bb_u.l.bb_pad = 0; 1007 1005 buf->bb_u.l.bb_lsn = 0; 1008 1006 } ··· 1015 1013 if (flags & XFS_BTREE_CRC_BLOCKS) { 1016 1014 buf->bb_u.s.bb_blkno = cpu_to_be64(blkno); 1017 1015 buf->bb_u.s.bb_owner = cpu_to_be32(__owner); 1018 - uuid_copy(&buf->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid); 1016 + uuid_copy(&buf->bb_u.s.bb_uuid, &mp->m_sb.sb_meta_uuid); 1019 1017 buf->bb_u.s.bb_lsn = 0; 1020 1018 } 1021 1019 }
+2 -2
fs/xfs/libxfs/xfs_da_btree.c
··· 146 146 if (ichdr.magic != XFS_DA3_NODE_MAGIC) 147 147 return false; 148 148 149 - if (!uuid_equal(&hdr3->info.uuid, &mp->m_sb.sb_uuid)) 149 + if (!uuid_equal(&hdr3->info.uuid, &mp->m_sb.sb_meta_uuid)) 150 150 return false; 151 151 if (be64_to_cpu(hdr3->info.blkno) != bp->b_bn) 152 152 return false; ··· 324 324 ichdr.magic = XFS_DA3_NODE_MAGIC; 325 325 hdr3->info.blkno = cpu_to_be64(bp->b_bn); 326 326 hdr3->info.owner = cpu_to_be64(args->dp->i_ino); 327 - uuid_copy(&hdr3->info.uuid, &mp->m_sb.sb_uuid); 327 + uuid_copy(&hdr3->info.uuid, &mp->m_sb.sb_meta_uuid); 328 328 } else { 329 329 ichdr.magic = XFS_DA_NODE_MAGIC; 330 330 }
+2 -2
fs/xfs/libxfs/xfs_dir2_block.c
··· 67 67 if (xfs_sb_version_hascrc(&mp->m_sb)) { 68 68 if (hdr3->magic != cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) 69 69 return false; 70 - if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_uuid)) 70 + if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid)) 71 71 return false; 72 72 if (be64_to_cpu(hdr3->blkno) != bp->b_bn) 73 73 return false; ··· 157 157 hdr3->magic = cpu_to_be32(XFS_DIR3_BLOCK_MAGIC); 158 158 hdr3->blkno = cpu_to_be64(bp->b_bn); 159 159 hdr3->owner = cpu_to_be64(dp->i_ino); 160 - uuid_copy(&hdr3->uuid, &mp->m_sb.sb_uuid); 160 + uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid); 161 161 return; 162 162 163 163 }
+2 -2
fs/xfs/libxfs/xfs_dir2_data.c
··· 220 220 if (xfs_sb_version_hascrc(&mp->m_sb)) { 221 221 if (hdr3->magic != cpu_to_be32(XFS_DIR3_DATA_MAGIC)) 222 222 return false; 223 - if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_uuid)) 223 + if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid)) 224 224 return false; 225 225 if (be64_to_cpu(hdr3->blkno) != bp->b_bn) 226 226 return false; ··· 604 604 hdr3->magic = cpu_to_be32(XFS_DIR3_DATA_MAGIC); 605 605 hdr3->blkno = cpu_to_be64(bp->b_bn); 606 606 hdr3->owner = cpu_to_be64(dp->i_ino); 607 - uuid_copy(&hdr3->uuid, &mp->m_sb.sb_uuid); 607 + uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid); 608 608 609 609 } else 610 610 hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
+2 -2
fs/xfs/libxfs/xfs_dir2_leaf.c
··· 160 160 161 161 if (leaf3->info.hdr.magic != cpu_to_be16(magic3)) 162 162 return false; 163 - if (!uuid_equal(&leaf3->info.uuid, &mp->m_sb.sb_uuid)) 163 + if (!uuid_equal(&leaf3->info.uuid, &mp->m_sb.sb_meta_uuid)) 164 164 return false; 165 165 if (be64_to_cpu(leaf3->info.blkno) != bp->b_bn) 166 166 return false; ··· 310 310 : cpu_to_be16(XFS_DIR3_LEAFN_MAGIC); 311 311 leaf3->info.blkno = cpu_to_be64(bp->b_bn); 312 312 leaf3->info.owner = cpu_to_be64(owner); 313 - uuid_copy(&leaf3->info.uuid, &mp->m_sb.sb_uuid); 313 + uuid_copy(&leaf3->info.uuid, &mp->m_sb.sb_meta_uuid); 314 314 } else { 315 315 memset(leaf, 0, sizeof(*leaf)); 316 316 leaf->hdr.info.magic = cpu_to_be16(type);
+2 -2
fs/xfs/libxfs/xfs_dir2_node.c
··· 93 93 94 94 if (hdr3->magic != cpu_to_be32(XFS_DIR3_FREE_MAGIC)) 95 95 return false; 96 - if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_uuid)) 96 + if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid)) 97 97 return false; 98 98 if (be64_to_cpu(hdr3->blkno) != bp->b_bn) 99 99 return false; ··· 226 226 227 227 hdr3->hdr.blkno = cpu_to_be64(bp->b_bn); 228 228 hdr3->hdr.owner = cpu_to_be64(dp->i_ino); 229 - uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_uuid); 229 + uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_meta_uuid); 230 230 } else 231 231 hdr.magic = XFS_DIR2_FREE_MAGIC; 232 232 dp->d_ops->free_hdr_to_disk(bp->b_addr, &hdr);
+2 -2
fs/xfs/libxfs/xfs_dquot_buf.c
··· 163 163 d->dd_diskdq.d_id = cpu_to_be32(id); 164 164 165 165 if (xfs_sb_version_hascrc(&mp->m_sb)) { 166 - uuid_copy(&d->dd_uuid, &mp->m_sb.sb_uuid); 166 + uuid_copy(&d->dd_uuid, &mp->m_sb.sb_meta_uuid); 167 167 xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk), 168 168 XFS_DQUOT_CRC_OFF); 169 169 } ··· 198 198 if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk), 199 199 XFS_DQUOT_CRC_OFF)) 200 200 return false; 201 - if (!uuid_equal(&d->dd_uuid, &mp->m_sb.sb_uuid)) 201 + if (!uuid_equal(&d->dd_uuid, &mp->m_sb.sb_meta_uuid)) 202 202 return false; 203 203 } 204 204 return true;
+19 -3
fs/xfs/libxfs/xfs_format.h
··· 100 100 xfs_rfsblock_t sb_dblocks; /* number of data blocks */ 101 101 xfs_rfsblock_t sb_rblocks; /* number of realtime blocks */ 102 102 xfs_rtblock_t sb_rextents; /* number of realtime extents */ 103 - uuid_t sb_uuid; /* file system unique id */ 103 + uuid_t sb_uuid; /* user-visible file system unique id */ 104 104 xfs_fsblock_t sb_logstart; /* starting block of log if internal */ 105 105 xfs_ino_t sb_rootino; /* root inode number */ 106 106 xfs_ino_t sb_rbmino; /* bitmap inode for realtime extents */ ··· 174 174 175 175 xfs_ino_t sb_pquotino; /* project quota inode */ 176 176 xfs_lsn_t sb_lsn; /* last write sequence */ 177 + uuid_t sb_meta_uuid; /* metadata file system unique id */ 177 178 178 179 /* must be padded to 64 bit alignment */ 179 180 } xfs_sb_t; ··· 191 190 __be64 sb_dblocks; /* number of data blocks */ 192 191 __be64 sb_rblocks; /* number of realtime blocks */ 193 192 __be64 sb_rextents; /* number of realtime extents */ 194 - uuid_t sb_uuid; /* file system unique id */ 193 + uuid_t sb_uuid; /* user-visible file system unique id */ 195 194 __be64 sb_logstart; /* starting block of log if internal */ 196 195 __be64 sb_rootino; /* root inode number */ 197 196 __be64 sb_rbmino; /* bitmap inode for realtime extents */ ··· 261 260 262 261 __be64 sb_pquotino; /* project quota inode */ 263 262 __be64 sb_lsn; /* last write sequence */ 263 + uuid_t sb_meta_uuid; /* metadata file system unique id */ 264 264 265 265 /* must be padded to 64 bit alignment */ 266 266 } xfs_dsb_t; ··· 460 458 461 459 #define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ 462 460 #define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */ 461 + #define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */ 463 462 #define XFS_SB_FEAT_INCOMPAT_ALL \ 464 463 (XFS_SB_FEAT_INCOMPAT_FTYPE| \ 465 - XFS_SB_FEAT_INCOMPAT_SPINODES) 464 + XFS_SB_FEAT_INCOMPAT_SPINODES| \ 465 + XFS_SB_FEAT_INCOMPAT_META_UUID) 466 466 467 467 #define XFS_SB_FEAT_INCOMPAT_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_ALL 468 468 static inline bool ··· 516 512 { 517 513 return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 && 518 514 xfs_sb_has_incompat_feature(sbp, XFS_SB_FEAT_INCOMPAT_SPINODES); 515 + } 516 + 517 + /* 518 + * XFS_SB_FEAT_INCOMPAT_META_UUID indicates that the metadata UUID 519 + * is stored separately from the user-visible UUID; this allows the 520 + * user-visible UUID to be changed on V5 filesystems which have a 521 + * filesystem UUID stamped into every piece of metadata. 522 + */ 523 + static inline bool xfs_sb_version_hasmetauuid(struct xfs_sb *sbp) 524 + { 525 + return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) && 526 + (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_META_UUID); 519 527 } 520 528 521 529 /*
+3 -2
fs/xfs/libxfs/xfs_ialloc.c
··· 338 338 if (version == 3) { 339 339 free->di_ino = cpu_to_be64(ino); 340 340 ino++; 341 - uuid_copy(&free->di_uuid, &mp->m_sb.sb_uuid); 341 + uuid_copy(&free->di_uuid, 342 + &mp->m_sb.sb_meta_uuid); 342 343 xfs_dinode_calc_crc(mp, free); 343 344 } else if (tp) { 344 345 /* just log the inode core */ ··· 2501 2500 struct xfs_agi *agi = XFS_BUF_TO_AGI(bp); 2502 2501 2503 2502 if (xfs_sb_version_hascrc(&mp->m_sb) && 2504 - !uuid_equal(&agi->agi_uuid, &mp->m_sb.sb_uuid)) 2503 + !uuid_equal(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid)) 2505 2504 return false; 2506 2505 /* 2507 2506 * Validate the magic number of the agi block.
+1 -1
fs/xfs/libxfs/xfs_ialloc_btree.c
··· 239 239 case cpu_to_be32(XFS_FIBT_CRC_MAGIC): 240 240 if (!xfs_sb_version_hascrc(&mp->m_sb)) 241 241 return false; 242 - if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid)) 242 + if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_meta_uuid)) 243 243 return false; 244 244 if (block->bb_u.s.bb_blkno != cpu_to_be64(bp->b_bn)) 245 245 return false;
+2 -2
fs/xfs/libxfs/xfs_inode_buf.c
··· 304 304 return false; 305 305 if (be64_to_cpu(dip->di_ino) != ip->i_ino) 306 306 return false; 307 - if (!uuid_equal(&dip->di_uuid, &mp->m_sb.sb_uuid)) 307 + if (!uuid_equal(&dip->di_uuid, &mp->m_sb.sb_meta_uuid)) 308 308 return false; 309 309 return true; 310 310 } ··· 366 366 if (xfs_sb_version_hascrc(&mp->m_sb)) { 367 367 ip->i_d.di_version = 3; 368 368 ip->i_d.di_ino = ip->i_ino; 369 - uuid_copy(&ip->i_d.di_uuid, &mp->m_sb.sb_uuid); 369 + uuid_copy(&ip->i_d.di_uuid, &mp->m_sb.sb_meta_uuid); 370 370 } else 371 371 ip->i_d.di_version = 2; 372 372 return 0;
+10
fs/xfs/libxfs/xfs_sb.c
··· 398 398 to->sb_spino_align = be32_to_cpu(from->sb_spino_align); 399 399 to->sb_pquotino = be64_to_cpu(from->sb_pquotino); 400 400 to->sb_lsn = be64_to_cpu(from->sb_lsn); 401 + /* 402 + * sb_meta_uuid is only on disk if it differs from sb_uuid and the 403 + * feature flag is set; if not set we keep it only in memory. 404 + */ 405 + if (xfs_sb_version_hasmetauuid(to)) 406 + uuid_copy(&to->sb_meta_uuid, &from->sb_meta_uuid); 407 + else 408 + uuid_copy(&to->sb_meta_uuid, &from->sb_uuid); 401 409 /* Convert on-disk flags to in-memory flags? */ 402 410 if (convert_xquota) 403 411 xfs_sb_quota_from_disk(to); ··· 547 539 cpu_to_be32(from->sb_features_log_incompat); 548 540 to->sb_spino_align = cpu_to_be32(from->sb_spino_align); 549 541 to->sb_lsn = cpu_to_be64(from->sb_lsn); 542 + if (xfs_sb_version_hasmetauuid(from)) 543 + uuid_copy(&to->sb_meta_uuid, &from->sb_meta_uuid); 550 544 } 551 545 } 552 546