xref: /linux/fs/befs/super.c (revision 24bce201d79807b668bf9d9e0aca801c5c0d5f78)
1 /*
2  * super.c
3  *
4  * Copyright (C) 2001-2002 Will Dyson <will_dyson@pobox.com>
5  *
6  * Licensed under the GNU GPL. See the file COPYING for details.
7  *
8  */
9 
10 #include <linux/fs.h>
11 #include <asm/page.h> /* for PAGE_SIZE */
12 
13 #include "befs.h"
14 #include "super.h"
15 
16 /*
17  * befs_load_sb -- Read from disk and properly byteswap all the fields
18  * of the befs superblock
19  */
20 int
21 befs_load_sb(struct super_block *sb, befs_super_block *disk_sb)
22 {
23 	struct befs_sb_info *befs_sb = BEFS_SB(sb);
24 
25 	/* Check the byte order of the filesystem */
26 	if (disk_sb->fs_byte_order == BEFS_BYTEORDER_NATIVE_LE)
27 		befs_sb->byte_order = BEFS_BYTESEX_LE;
28 	else if (disk_sb->fs_byte_order == BEFS_BYTEORDER_NATIVE_BE)
29 		befs_sb->byte_order = BEFS_BYTESEX_BE;
30 
31 	befs_sb->magic1 = fs32_to_cpu(sb, disk_sb->magic1);
32 	befs_sb->magic2 = fs32_to_cpu(sb, disk_sb->magic2);
33 	befs_sb->magic3 = fs32_to_cpu(sb, disk_sb->magic3);
34 	befs_sb->block_size = fs32_to_cpu(sb, disk_sb->block_size);
35 	befs_sb->block_shift = fs32_to_cpu(sb, disk_sb->block_shift);
36 	befs_sb->num_blocks = fs64_to_cpu(sb, disk_sb->num_blocks);
37 	befs_sb->used_blocks = fs64_to_cpu(sb, disk_sb->used_blocks);
38 	befs_sb->inode_size = fs32_to_cpu(sb, disk_sb->inode_size);
39 
40 	befs_sb->blocks_per_ag = fs32_to_cpu(sb, disk_sb->blocks_per_ag);
41 	befs_sb->ag_shift = fs32_to_cpu(sb, disk_sb->ag_shift);
42 	befs_sb->num_ags = fs32_to_cpu(sb, disk_sb->num_ags);
43 
44 	befs_sb->flags = fs32_to_cpu(sb, disk_sb->flags);
45 
46 	befs_sb->log_blocks = fsrun_to_cpu(sb, disk_sb->log_blocks);
47 	befs_sb->log_start = fs64_to_cpu(sb, disk_sb->log_start);
48 	befs_sb->log_end = fs64_to_cpu(sb, disk_sb->log_end);
49 
50 	befs_sb->root_dir = fsrun_to_cpu(sb, disk_sb->root_dir);
51 	befs_sb->indices = fsrun_to_cpu(sb, disk_sb->indices);
52 	befs_sb->nls = NULL;
53 
54 	return BEFS_OK;
55 }
56 
57 int
58 befs_check_sb(struct super_block *sb)
59 {
60 	struct befs_sb_info *befs_sb = BEFS_SB(sb);
61 
62 	/* Check magic headers of super block */
63 	if ((befs_sb->magic1 != BEFS_SUPER_MAGIC1)
64 	    || (befs_sb->magic2 != BEFS_SUPER_MAGIC2)
65 	    || (befs_sb->magic3 != BEFS_SUPER_MAGIC3)) {
66 		befs_error(sb, "invalid magic header");
67 		return BEFS_ERR;
68 	}
69 
70 	/*
71 	 * Check blocksize of BEFS.
72 	 *
73 	 * Blocksize of BEFS is 1024, 2048, 4096 or 8192.
74 	 */
75 
76 	if ((befs_sb->block_size != 1024)
77 	    && (befs_sb->block_size != 2048)
78 	    && (befs_sb->block_size != 4096)
79 	    && (befs_sb->block_size != 8192)) {
80 		befs_error(sb, "invalid blocksize: %u", befs_sb->block_size);
81 		return BEFS_ERR;
82 	}
83 
84 	if (befs_sb->block_size > PAGE_SIZE) {
85 		befs_error(sb, "blocksize(%u) cannot be larger "
86 			   "than system pagesize(%lu)", befs_sb->block_size,
87 			   PAGE_SIZE);
88 		return BEFS_ERR;
89 	}
90 
91 	/*
92 	 * block_shift and block_size encode the same information
93 	 * in different ways as a consistency check.
94 	 */
95 
96 	if ((1 << befs_sb->block_shift) != befs_sb->block_size) {
97 		befs_error(sb, "block_shift disagrees with block_size. "
98 			   "Corruption likely.");
99 		return BEFS_ERR;
100 	}
101 
102 
103 	/* ag_shift also encodes the same information as blocks_per_ag in a
104 	 * different way, non-fatal consistency check
105 	 */
106 	if ((1 << befs_sb->ag_shift) != befs_sb->blocks_per_ag)
107 		befs_error(sb, "ag_shift disagrees with blocks_per_ag.");
108 
109 	if (befs_sb->log_start != befs_sb->log_end ||
110 	    befs_sb->flags == BEFS_DIRTY) {
111 		befs_error(sb, "Filesystem not clean! There are blocks in the "
112 			   "journal. You must boot into BeOS and mount this "
113 			   "volume to make it clean.");
114 		return BEFS_ERR;
115 	}
116 
117 	return BEFS_OK;
118 }
119