]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libblkid: (nilfs2) check also backup superblock
authorKarel Zak <kzak@redhat.com>
Mon, 13 Jan 2014 13:30:51 +0000 (14:30 +0100)
committerKarel Zak <kzak@redhat.com>
Mon, 13 Jan 2014 13:32:06 +0000 (14:32 +0100)
* read also backup superblock
* check which superblock is newer
* set minimal device size to 1MiB

Reported-by: Phillip Susi <psusi@ubuntu.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
libblkid/src/superblocks/nilfs.c

index 9207677a9976de5e13362885f61b47366bc23c95..24ccf633e6f47163dd7f767009d586f1fc268ea1 100644 (file)
@@ -63,35 +63,60 @@ struct nilfs_super_block {
        uint32_t        s_reserved[192];
 };
 
-/* nilfs2 magic string */
-#define NILFS_SB_MAGIC         "\x34\x34"
-/* nilfs2 super block offset */
-#define NILFS_SB_OFF           0x400
-/* nilfs2 super block offset in kB */
-#define NILFS_SB_KBOFF         (NILFS_SB_OFF >> 10)
-/* nilfs2 magic string offset within super block */
-#define NILFS_MAG_OFF          6
+#define NILFS_SB_MAGIC         0x3434
+#define NILFS_SB_OFFSET                0x400
 
-static int probe_nilfs2(blkid_probe pr, const struct blkid_idmag *mag)
+static int nilfs_valid_sb(blkid_probe pr, struct nilfs_super_block *sb)
 {
-       struct nilfs_super_block *sb;
        static unsigned char sum[4];
        const int sumoff = offsetof(struct nilfs_super_block, s_sum);
        size_t bytes;
        uint32_t crc;
 
-       sb = blkid_probe_get_sb(pr, mag, struct nilfs_super_block);
-       if (!sb)
-               return -1;
+       if (!sb || le16_to_cpu(sb->s_magic) != NILFS_SB_MAGIC)
+               return 0;
 
        bytes = le16_to_cpu(sb->s_bytes);
        crc = crc32(le32_to_cpu(sb->s_crc_seed), (unsigned char *)sb, sumoff);
        crc = crc32(crc, sum, 4);
        crc = crc32(crc, (unsigned char *)sb + sumoff + 4, bytes - sumoff - 4);
 
-       if (!blkid_probe_verify_csum(pr, crc, le32_to_cpu(sb->s_sum)))
+       return blkid_probe_verify_csum(pr, crc, le32_to_cpu(sb->s_sum));
+}
+
+static int probe_nilfs2(blkid_probe pr, const struct blkid_idmag *mag)
+{
+       struct nilfs_super_block *sb, *sbp, *sbb;
+       int valid[2], swp = 0;
+
+       /* primary */
+       sbp = (struct nilfs_super_block *) blkid_probe_get_buffer(
+                       pr, NILFS_SB_OFFSET, sizeof(struct nilfs_super_block));
+       if (!sbp)
+               return -1;
+       /* backup */
+       sbb = (struct nilfs_super_block *) blkid_probe_get_buffer(
+                       pr, ((pr->size / 0x200) - 8) * 0x200, sizeof(struct nilfs_super_block));
+       if (!sbp)
+               return -1;
+
+       /*
+        * Compare two super blocks and set 1 in swp if the secondary
+        * super block is valid and newer.  Otherwise, set 0 in swp.
+        */
+       valid[0] = nilfs_valid_sb(pr, sbp);
+       valid[1] = nilfs_valid_sb(pr, sbb);
+       if (!valid[0] && !valid[1])
                return 1;
 
+       swp = valid[1] && (!valid[0] ||
+                          le64_to_cpu(sbp->s_last_cno) >
+                          le64_to_cpu(sbb->s_last_cno));
+       sb = swp ? sbb : sbp;
+
+       DBG(LOWPROBE, blkid_debug("nilfs2: primary=%d, backup=%d, swap=%d",
+                               valid[0], valid[1], swp));
+
        if (strlen(sb->s_volume_name))
                blkid_probe_set_label(pr, (unsigned char *) sb->s_volume_name,
                                      sizeof(sb->s_volume_name));
@@ -107,14 +132,7 @@ const struct blkid_idinfo nilfs2_idinfo =
        .name           = "nilfs2",
        .usage          = BLKID_USAGE_FILESYSTEM,
        .probefunc      = probe_nilfs2,
-       .magics         =
-       {
-               {
-                       .magic = NILFS_SB_MAGIC,
-                       .len = 2,
-                       .kboff = NILFS_SB_KBOFF,
-                       .sboff = NILFS_MAG_OFF
-               },
-               { NULL }
-       }
+       /* default min.size is 128MiB, but 1MiB for "mkfs.nilfs2 -b 1024 -B 16" */
+       .minsz          = (1024 * 1024),
+       .magics         = BLKID_NONE_MAGIC
 };