Blame view

fs/qnx6/super_mmi.c 3.8 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
5d026c724   Kai Bankett   fs: initial qnx6f...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
  /*
   * QNX6 file system, Linux implementation.
   *
   * Version : 1.0.0
   *
   * History :
   *
   * 01-02-2012 by Kai Bankett (chaosman@ontika.net) : first release.
   *
   */
  
  #include <linux/buffer_head.h>
  #include <linux/slab.h>
  #include <linux/crc32.h>
  #include "qnx6.h"
  
  static void qnx6_mmi_copy_sb(struct qnx6_super_block *qsb,
  		struct qnx6_mmi_super_block *sb)
  {
  	qsb->sb_magic = sb->sb_magic;
  	qsb->sb_checksum = sb->sb_checksum;
  	qsb->sb_serial = sb->sb_serial;
  	qsb->sb_blocksize = sb->sb_blocksize;
  	qsb->sb_num_inodes = sb->sb_num_inodes;
  	qsb->sb_free_inodes = sb->sb_free_inodes;
  	qsb->sb_num_blocks = sb->sb_num_blocks;
  	qsb->sb_free_blocks = sb->sb_free_blocks;
  
  	/* the rest of the superblock is the same */
  	memcpy(&qsb->Inode, &sb->Inode, sizeof(sb->Inode));
  	memcpy(&qsb->Bitmap, &sb->Bitmap, sizeof(sb->Bitmap));
  	memcpy(&qsb->Longfile, &sb->Longfile, sizeof(sb->Longfile));
  }
  
  struct qnx6_super_block *qnx6_mmi_fill_super(struct super_block *s, int silent)
  {
  	struct buffer_head *bh1, *bh2 = NULL;
  	struct qnx6_mmi_super_block *sb1, *sb2;
  	struct qnx6_super_block *qsb = NULL;
  	struct qnx6_sb_info *sbi;
  	__u64 offset;
  
  	/* Check the superblock signatures
  	   start with the first superblock */
  	bh1 = sb_bread(s, 0);
  	if (!bh1) {
e6c326165   Fabian Frederick   fs/qnx6: use pr_f...
48
49
  		pr_err("Unable to read first mmi superblock
  ");
5d026c724   Kai Bankett   fs: initial qnx6f...
50
51
52
53
54
55
  		return NULL;
  	}
  	sb1 = (struct qnx6_mmi_super_block *)bh1->b_data;
  	sbi = QNX6_SB(s);
  	if (fs32_to_cpu(sbi, sb1->sb_magic) != QNX6_SUPER_MAGIC) {
  		if (!silent) {
e6c326165   Fabian Frederick   fs/qnx6: use pr_f...
56
57
  			pr_err("wrong signature (magic) in superblock #1.
  ");
5d026c724   Kai Bankett   fs: initial qnx6f...
58
59
60
61
62
63
64
  			goto out;
  		}
  	}
  
  	/* checksum check - start at byte 8 and end at byte 512 */
  	if (fs32_to_cpu(sbi, sb1->sb_checksum) !=
  				crc32_be(0, (char *)(bh1->b_data + 8), 504)) {
e6c326165   Fabian Frederick   fs/qnx6: use pr_f...
65
66
  		pr_err("superblock #1 checksum error
  ");
5d026c724   Kai Bankett   fs: initial qnx6f...
67
68
69
70
71
72
73
74
75
  		goto out;
  	}
  
  	/* calculate second superblock blocknumber */
  	offset = fs32_to_cpu(sbi, sb1->sb_num_blocks) + QNX6_SUPERBLOCK_AREA /
  					fs32_to_cpu(sbi, sb1->sb_blocksize);
  
  	/* set new blocksize */
  	if (!sb_set_blocksize(s, fs32_to_cpu(sbi, sb1->sb_blocksize))) {
e6c326165   Fabian Frederick   fs/qnx6: use pr_f...
76
77
  		pr_err("unable to set blocksize
  ");
5d026c724   Kai Bankett   fs: initial qnx6f...
78
79
80
81
82
83
84
85
86
87
88
89
  		goto out;
  	}
  	/* blocksize invalidates bh - pull it back in */
  	brelse(bh1);
  	bh1 = sb_bread(s, 0);
  	if (!bh1)
  		goto out;
  	sb1 = (struct qnx6_mmi_super_block *)bh1->b_data;
  
  	/* read second superblock */
  	bh2 = sb_bread(s, offset);
  	if (!bh2) {
e6c326165   Fabian Frederick   fs/qnx6: use pr_f...
90
91
  		pr_err("unable to read the second superblock
  ");
5d026c724   Kai Bankett   fs: initial qnx6f...
92
93
94
95
96
  		goto out;
  	}
  	sb2 = (struct qnx6_mmi_super_block *)bh2->b_data;
  	if (fs32_to_cpu(sbi, sb2->sb_magic) != QNX6_SUPER_MAGIC) {
  		if (!silent)
e6c326165   Fabian Frederick   fs/qnx6: use pr_f...
97
98
  			pr_err("wrong signature (magic) in superblock #2.
  ");
5d026c724   Kai Bankett   fs: initial qnx6f...
99
100
101
102
103
104
  		goto out;
  	}
  
  	/* checksum check - start at byte 8 and end at byte 512 */
  	if (fs32_to_cpu(sbi, sb2->sb_checksum)
  			!= crc32_be(0, (char *)(bh2->b_data + 8), 504)) {
e6c326165   Fabian Frederick   fs/qnx6: use pr_f...
105
106
  		pr_err("superblock #1 checksum error
  ");
5d026c724   Kai Bankett   fs: initial qnx6f...
107
108
109
110
111
  		goto out;
  	}
  
  	qsb = kmalloc(sizeof(*qsb), GFP_KERNEL);
  	if (!qsb) {
e6c326165   Fabian Frederick   fs/qnx6: use pr_f...
112
113
  		pr_err("unable to allocate memory.
  ");
5d026c724   Kai Bankett   fs: initial qnx6f...
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
  		goto out;
  	}
  
  	if (fs64_to_cpu(sbi, sb1->sb_serial) >
  					fs64_to_cpu(sbi, sb2->sb_serial)) {
  		/* superblock #1 active */
  		qnx6_mmi_copy_sb(qsb, sb1);
  #ifdef CONFIG_QNX6FS_DEBUG
  		qnx6_superblock_debug(qsb, s);
  #endif
  		memcpy(bh1->b_data, qsb, sizeof(struct qnx6_super_block));
  
  		sbi->sb_buf = bh1;
  		sbi->sb = (struct qnx6_super_block *)bh1->b_data;
  		brelse(bh2);
e6c326165   Fabian Frederick   fs/qnx6: use pr_f...
129
130
  		pr_info("superblock #1 active
  ");
5d026c724   Kai Bankett   fs: initial qnx6f...
131
132
133
134
135
136
137
138
139
140
141
  	} else {
  		/* superblock #2 active */
  		qnx6_mmi_copy_sb(qsb, sb2);
  #ifdef CONFIG_QNX6FS_DEBUG
  		qnx6_superblock_debug(qsb, s);
  #endif
  		memcpy(bh2->b_data, qsb, sizeof(struct qnx6_super_block));
  
  		sbi->sb_buf = bh2;
  		sbi->sb = (struct qnx6_super_block *)bh2->b_data;
  		brelse(bh1);
e6c326165   Fabian Frederick   fs/qnx6: use pr_f...
142
143
  		pr_info("superblock #2 active
  ");
5d026c724   Kai Bankett   fs: initial qnx6f...
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
  	}
  	kfree(qsb);
  
  	/* offset for mmi_fs is just SUPERBLOCK_AREA bytes */
  	sbi->s_blks_off = QNX6_SUPERBLOCK_AREA / s->s_blocksize;
  
  	/* success */
  	return sbi->sb;
  
  out:
  	if (bh1 != NULL)
  		brelse(bh1);
  	if (bh2 != NULL)
  		brelse(bh2);
  	return NULL;
  }