Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * QNX6 file system, Linux implementation.
0004  *
0005  * Version : 1.0.0
0006  *
0007  * History :
0008  *
0009  * 01-02-2012 by Kai Bankett (chaosman@ontika.net) : first release.
0010  *
0011  */
0012 
0013 #include <linux/buffer_head.h>
0014 #include <linux/slab.h>
0015 #include <linux/crc32.h>
0016 #include "qnx6.h"
0017 
0018 static void qnx6_mmi_copy_sb(struct qnx6_super_block *qsb,
0019         struct qnx6_mmi_super_block *sb)
0020 {
0021     qsb->sb_magic = sb->sb_magic;
0022     qsb->sb_checksum = sb->sb_checksum;
0023     qsb->sb_serial = sb->sb_serial;
0024     qsb->sb_blocksize = sb->sb_blocksize;
0025     qsb->sb_num_inodes = sb->sb_num_inodes;
0026     qsb->sb_free_inodes = sb->sb_free_inodes;
0027     qsb->sb_num_blocks = sb->sb_num_blocks;
0028     qsb->sb_free_blocks = sb->sb_free_blocks;
0029 
0030     /* the rest of the superblock is the same */
0031     memcpy(&qsb->Inode, &sb->Inode, sizeof(sb->Inode));
0032     memcpy(&qsb->Bitmap, &sb->Bitmap, sizeof(sb->Bitmap));
0033     memcpy(&qsb->Longfile, &sb->Longfile, sizeof(sb->Longfile));
0034 }
0035 
0036 struct qnx6_super_block *qnx6_mmi_fill_super(struct super_block *s, int silent)
0037 {
0038     struct buffer_head *bh1, *bh2 = NULL;
0039     struct qnx6_mmi_super_block *sb1, *sb2;
0040     struct qnx6_super_block *qsb = NULL;
0041     struct qnx6_sb_info *sbi;
0042     __u64 offset;
0043 
0044     /* Check the superblock signatures
0045        start with the first superblock */
0046     bh1 = sb_bread(s, 0);
0047     if (!bh1) {
0048         pr_err("Unable to read first mmi superblock\n");
0049         return NULL;
0050     }
0051     sb1 = (struct qnx6_mmi_super_block *)bh1->b_data;
0052     sbi = QNX6_SB(s);
0053     if (fs32_to_cpu(sbi, sb1->sb_magic) != QNX6_SUPER_MAGIC) {
0054         if (!silent) {
0055             pr_err("wrong signature (magic) in superblock #1.\n");
0056             goto out;
0057         }
0058     }
0059 
0060     /* checksum check - start at byte 8 and end at byte 512 */
0061     if (fs32_to_cpu(sbi, sb1->sb_checksum) !=
0062                 crc32_be(0, (char *)(bh1->b_data + 8), 504)) {
0063         pr_err("superblock #1 checksum error\n");
0064         goto out;
0065     }
0066 
0067     /* calculate second superblock blocknumber */
0068     offset = fs32_to_cpu(sbi, sb1->sb_num_blocks) + QNX6_SUPERBLOCK_AREA /
0069                     fs32_to_cpu(sbi, sb1->sb_blocksize);
0070 
0071     /* set new blocksize */
0072     if (!sb_set_blocksize(s, fs32_to_cpu(sbi, sb1->sb_blocksize))) {
0073         pr_err("unable to set blocksize\n");
0074         goto out;
0075     }
0076     /* blocksize invalidates bh - pull it back in */
0077     brelse(bh1);
0078     bh1 = sb_bread(s, 0);
0079     if (!bh1)
0080         goto out;
0081     sb1 = (struct qnx6_mmi_super_block *)bh1->b_data;
0082 
0083     /* read second superblock */
0084     bh2 = sb_bread(s, offset);
0085     if (!bh2) {
0086         pr_err("unable to read the second superblock\n");
0087         goto out;
0088     }
0089     sb2 = (struct qnx6_mmi_super_block *)bh2->b_data;
0090     if (fs32_to_cpu(sbi, sb2->sb_magic) != QNX6_SUPER_MAGIC) {
0091         if (!silent)
0092             pr_err("wrong signature (magic) in superblock #2.\n");
0093         goto out;
0094     }
0095 
0096     /* checksum check - start at byte 8 and end at byte 512 */
0097     if (fs32_to_cpu(sbi, sb2->sb_checksum)
0098             != crc32_be(0, (char *)(bh2->b_data + 8), 504)) {
0099         pr_err("superblock #1 checksum error\n");
0100         goto out;
0101     }
0102 
0103     qsb = kmalloc(sizeof(*qsb), GFP_KERNEL);
0104     if (!qsb) {
0105         pr_err("unable to allocate memory.\n");
0106         goto out;
0107     }
0108 
0109     if (fs64_to_cpu(sbi, sb1->sb_serial) >
0110                     fs64_to_cpu(sbi, sb2->sb_serial)) {
0111         /* superblock #1 active */
0112         qnx6_mmi_copy_sb(qsb, sb1);
0113 #ifdef CONFIG_QNX6FS_DEBUG
0114         qnx6_superblock_debug(qsb, s);
0115 #endif
0116         memcpy(bh1->b_data, qsb, sizeof(struct qnx6_super_block));
0117 
0118         sbi->sb_buf = bh1;
0119         sbi->sb = (struct qnx6_super_block *)bh1->b_data;
0120         brelse(bh2);
0121         pr_info("superblock #1 active\n");
0122     } else {
0123         /* superblock #2 active */
0124         qnx6_mmi_copy_sb(qsb, sb2);
0125 #ifdef CONFIG_QNX6FS_DEBUG
0126         qnx6_superblock_debug(qsb, s);
0127 #endif
0128         memcpy(bh2->b_data, qsb, sizeof(struct qnx6_super_block));
0129 
0130         sbi->sb_buf = bh2;
0131         sbi->sb = (struct qnx6_super_block *)bh2->b_data;
0132         brelse(bh1);
0133         pr_info("superblock #2 active\n");
0134     }
0135     kfree(qsb);
0136 
0137     /* offset for mmi_fs is just SUPERBLOCK_AREA bytes */
0138     sbi->s_blks_off = QNX6_SUPERBLOCK_AREA / s->s_blocksize;
0139 
0140     /* success */
0141     return sbi->sb;
0142 
0143 out:
0144     if (bh1 != NULL)
0145         brelse(bh1);
0146     if (bh2 != NULL)
0147         brelse(bh2);
0148     return NULL;
0149 }