xref: /linux/fs/jfs/jfs_mount.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /*
2*1da177e4SLinus Torvalds  *   Copyright (C) International Business Machines Corp., 2000-2004
3*1da177e4SLinus Torvalds  *
4*1da177e4SLinus Torvalds  *   This program is free software;  you can redistribute it and/or modify
5*1da177e4SLinus Torvalds  *   it under the terms of the GNU General Public License as published by
6*1da177e4SLinus Torvalds  *   the Free Software Foundation; either version 2 of the License, or
7*1da177e4SLinus Torvalds  *   (at your option) any later version.
8*1da177e4SLinus Torvalds  *
9*1da177e4SLinus Torvalds  *   This program is distributed in the hope that it will be useful,
10*1da177e4SLinus Torvalds  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
11*1da177e4SLinus Torvalds  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12*1da177e4SLinus Torvalds  *   the GNU General Public License for more details.
13*1da177e4SLinus Torvalds  *
14*1da177e4SLinus Torvalds  *   You should have received a copy of the GNU General Public License
15*1da177e4SLinus Torvalds  *   along with this program;  if not, write to the Free Software
16*1da177e4SLinus Torvalds  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17*1da177e4SLinus Torvalds  */
18*1da177e4SLinus Torvalds 
19*1da177e4SLinus Torvalds /*
20*1da177e4SLinus Torvalds  * Module: jfs_mount.c
21*1da177e4SLinus Torvalds  *
22*1da177e4SLinus Torvalds  * note: file system in transition to aggregate/fileset:
23*1da177e4SLinus Torvalds  *
24*1da177e4SLinus Torvalds  * file system mount is interpreted as the mount of aggregate,
25*1da177e4SLinus Torvalds  * if not already mounted, and mount of the single/only fileset in
26*1da177e4SLinus Torvalds  * the aggregate;
27*1da177e4SLinus Torvalds  *
28*1da177e4SLinus Torvalds  * a file system/aggregate is represented by an internal inode
29*1da177e4SLinus Torvalds  * (aka mount inode) initialized with aggregate superblock;
30*1da177e4SLinus Torvalds  * each vfs represents a fileset, and points to its "fileset inode
31*1da177e4SLinus Torvalds  * allocation map inode" (aka fileset inode):
32*1da177e4SLinus Torvalds  * (an aggregate itself is structured recursively as a filset:
33*1da177e4SLinus Torvalds  * an internal vfs is constructed and points to its "fileset inode
34*1da177e4SLinus Torvalds  * allocation map inode" (aka aggregate inode) where each inode
35*1da177e4SLinus Torvalds  * represents a fileset inode) so that inode number is mapped to
36*1da177e4SLinus Torvalds  * on-disk inode in uniform way at both aggregate and fileset level;
37*1da177e4SLinus Torvalds  *
38*1da177e4SLinus Torvalds  * each vnode/inode of a fileset is linked to its vfs (to facilitate
39*1da177e4SLinus Torvalds  * per fileset inode operations, e.g., unmount of a fileset, etc.);
40*1da177e4SLinus Torvalds  * each inode points to the mount inode (to facilitate access to
41*1da177e4SLinus Torvalds  * per aggregate information, e.g., block size, etc.) as well as
42*1da177e4SLinus Torvalds  * its file set inode.
43*1da177e4SLinus Torvalds  *
44*1da177e4SLinus Torvalds  *   aggregate
45*1da177e4SLinus Torvalds  *   ipmnt
46*1da177e4SLinus Torvalds  *   mntvfs -> fileset ipimap+ -> aggregate ipbmap -> aggregate ipaimap;
47*1da177e4SLinus Torvalds  *             fileset vfs     -> vp(1) <-> ... <-> vp(n) <->vproot;
48*1da177e4SLinus Torvalds  */
49*1da177e4SLinus Torvalds 
50*1da177e4SLinus Torvalds #include <linux/fs.h>
51*1da177e4SLinus Torvalds #include <linux/buffer_head.h>
52*1da177e4SLinus Torvalds 
53*1da177e4SLinus Torvalds #include "jfs_incore.h"
54*1da177e4SLinus Torvalds #include "jfs_filsys.h"
55*1da177e4SLinus Torvalds #include "jfs_superblock.h"
56*1da177e4SLinus Torvalds #include "jfs_dmap.h"
57*1da177e4SLinus Torvalds #include "jfs_imap.h"
58*1da177e4SLinus Torvalds #include "jfs_metapage.h"
59*1da177e4SLinus Torvalds #include "jfs_debug.h"
60*1da177e4SLinus Torvalds 
61*1da177e4SLinus Torvalds 
62*1da177e4SLinus Torvalds /*
63*1da177e4SLinus Torvalds  * forward references
64*1da177e4SLinus Torvalds  */
65*1da177e4SLinus Torvalds static int chkSuper(struct super_block *);
66*1da177e4SLinus Torvalds static int logMOUNT(struct super_block *sb);
67*1da177e4SLinus Torvalds 
68*1da177e4SLinus Torvalds /*
69*1da177e4SLinus Torvalds  * NAME:	jfs_mount(sb)
70*1da177e4SLinus Torvalds  *
71*1da177e4SLinus Torvalds  * FUNCTION:	vfs_mount()
72*1da177e4SLinus Torvalds  *
73*1da177e4SLinus Torvalds  * PARAMETER:	sb	- super block
74*1da177e4SLinus Torvalds  *
75*1da177e4SLinus Torvalds  * RETURN:	-EBUSY	- device already mounted or open for write
76*1da177e4SLinus Torvalds  *		-EBUSY	- cvrdvp already mounted;
77*1da177e4SLinus Torvalds  *		-EBUSY	- mount table full
78*1da177e4SLinus Torvalds  *		-ENOTDIR- cvrdvp not directory on a device mount
79*1da177e4SLinus Torvalds  *		-ENXIO	- device open failure
80*1da177e4SLinus Torvalds  */
81*1da177e4SLinus Torvalds int jfs_mount(struct super_block *sb)
82*1da177e4SLinus Torvalds {
83*1da177e4SLinus Torvalds 	int rc = 0;		/* Return code          */
84*1da177e4SLinus Torvalds 	struct jfs_sb_info *sbi = JFS_SBI(sb);
85*1da177e4SLinus Torvalds 	struct inode *ipaimap = NULL;
86*1da177e4SLinus Torvalds 	struct inode *ipaimap2 = NULL;
87*1da177e4SLinus Torvalds 	struct inode *ipimap = NULL;
88*1da177e4SLinus Torvalds 	struct inode *ipbmap = NULL;
89*1da177e4SLinus Torvalds 
90*1da177e4SLinus Torvalds 	/*
91*1da177e4SLinus Torvalds 	 * read/validate superblock
92*1da177e4SLinus Torvalds 	 * (initialize mount inode from the superblock)
93*1da177e4SLinus Torvalds 	 */
94*1da177e4SLinus Torvalds 	if ((rc = chkSuper(sb))) {
95*1da177e4SLinus Torvalds 		goto errout20;
96*1da177e4SLinus Torvalds 	}
97*1da177e4SLinus Torvalds 
98*1da177e4SLinus Torvalds 	ipaimap = diReadSpecial(sb, AGGREGATE_I, 0);
99*1da177e4SLinus Torvalds 	if (ipaimap == NULL) {
100*1da177e4SLinus Torvalds 		jfs_err("jfs_mount: Faild to read AGGREGATE_I");
101*1da177e4SLinus Torvalds 		rc = -EIO;
102*1da177e4SLinus Torvalds 		goto errout20;
103*1da177e4SLinus Torvalds 	}
104*1da177e4SLinus Torvalds 	sbi->ipaimap = ipaimap;
105*1da177e4SLinus Torvalds 
106*1da177e4SLinus Torvalds 	jfs_info("jfs_mount: ipaimap:0x%p", ipaimap);
107*1da177e4SLinus Torvalds 
108*1da177e4SLinus Torvalds 	/*
109*1da177e4SLinus Torvalds 	 * initialize aggregate inode allocation map
110*1da177e4SLinus Torvalds 	 */
111*1da177e4SLinus Torvalds 	if ((rc = diMount(ipaimap))) {
112*1da177e4SLinus Torvalds 		jfs_err("jfs_mount: diMount(ipaimap) failed w/rc = %d", rc);
113*1da177e4SLinus Torvalds 		goto errout21;
114*1da177e4SLinus Torvalds 	}
115*1da177e4SLinus Torvalds 
116*1da177e4SLinus Torvalds 	/*
117*1da177e4SLinus Torvalds 	 * open aggregate block allocation map
118*1da177e4SLinus Torvalds 	 */
119*1da177e4SLinus Torvalds 	ipbmap = diReadSpecial(sb, BMAP_I, 0);
120*1da177e4SLinus Torvalds 	if (ipbmap == NULL) {
121*1da177e4SLinus Torvalds 		rc = -EIO;
122*1da177e4SLinus Torvalds 		goto errout22;
123*1da177e4SLinus Torvalds 	}
124*1da177e4SLinus Torvalds 
125*1da177e4SLinus Torvalds 	jfs_info("jfs_mount: ipbmap:0x%p", ipbmap);
126*1da177e4SLinus Torvalds 
127*1da177e4SLinus Torvalds 	sbi->ipbmap = ipbmap;
128*1da177e4SLinus Torvalds 
129*1da177e4SLinus Torvalds 	/*
130*1da177e4SLinus Torvalds 	 * initialize aggregate block allocation map
131*1da177e4SLinus Torvalds 	 */
132*1da177e4SLinus Torvalds 	if ((rc = dbMount(ipbmap))) {
133*1da177e4SLinus Torvalds 		jfs_err("jfs_mount: dbMount failed w/rc = %d", rc);
134*1da177e4SLinus Torvalds 		goto errout22;
135*1da177e4SLinus Torvalds 	}
136*1da177e4SLinus Torvalds 
137*1da177e4SLinus Torvalds 	/*
138*1da177e4SLinus Torvalds 	 * open the secondary aggregate inode allocation map
139*1da177e4SLinus Torvalds 	 *
140*1da177e4SLinus Torvalds 	 * This is a duplicate of the aggregate inode allocation map.
141*1da177e4SLinus Torvalds 	 *
142*1da177e4SLinus Torvalds 	 * hand craft a vfs in the same fashion as we did to read ipaimap.
143*1da177e4SLinus Torvalds 	 * By adding INOSPEREXT (32) to the inode number, we are telling
144*1da177e4SLinus Torvalds 	 * diReadSpecial that we are reading from the secondary aggregate
145*1da177e4SLinus Torvalds 	 * inode table.  This also creates a unique entry in the inode hash
146*1da177e4SLinus Torvalds 	 * table.
147*1da177e4SLinus Torvalds 	 */
148*1da177e4SLinus Torvalds 	if ((sbi->mntflag & JFS_BAD_SAIT) == 0) {
149*1da177e4SLinus Torvalds 		ipaimap2 = diReadSpecial(sb, AGGREGATE_I, 1);
150*1da177e4SLinus Torvalds 		if (ipaimap2 == 0) {
151*1da177e4SLinus Torvalds 			jfs_err("jfs_mount: Faild to read AGGREGATE_I");
152*1da177e4SLinus Torvalds 			rc = -EIO;
153*1da177e4SLinus Torvalds 			goto errout35;
154*1da177e4SLinus Torvalds 		}
155*1da177e4SLinus Torvalds 		sbi->ipaimap2 = ipaimap2;
156*1da177e4SLinus Torvalds 
157*1da177e4SLinus Torvalds 		jfs_info("jfs_mount: ipaimap2:0x%p", ipaimap2);
158*1da177e4SLinus Torvalds 
159*1da177e4SLinus Torvalds 		/*
160*1da177e4SLinus Torvalds 		 * initialize secondary aggregate inode allocation map
161*1da177e4SLinus Torvalds 		 */
162*1da177e4SLinus Torvalds 		if ((rc = diMount(ipaimap2))) {
163*1da177e4SLinus Torvalds 			jfs_err("jfs_mount: diMount(ipaimap2) failed, rc = %d",
164*1da177e4SLinus Torvalds 				rc);
165*1da177e4SLinus Torvalds 			goto errout35;
166*1da177e4SLinus Torvalds 		}
167*1da177e4SLinus Torvalds 	} else
168*1da177e4SLinus Torvalds 		/* Secondary aggregate inode table is not valid */
169*1da177e4SLinus Torvalds 		sbi->ipaimap2 = NULL;
170*1da177e4SLinus Torvalds 
171*1da177e4SLinus Torvalds 	/*
172*1da177e4SLinus Torvalds 	 *      mount (the only/single) fileset
173*1da177e4SLinus Torvalds 	 */
174*1da177e4SLinus Torvalds 	/*
175*1da177e4SLinus Torvalds 	 * open fileset inode allocation map (aka fileset inode)
176*1da177e4SLinus Torvalds 	 */
177*1da177e4SLinus Torvalds 	ipimap = diReadSpecial(sb, FILESYSTEM_I, 0);
178*1da177e4SLinus Torvalds 	if (ipimap == NULL) {
179*1da177e4SLinus Torvalds 		jfs_err("jfs_mount: Failed to read FILESYSTEM_I");
180*1da177e4SLinus Torvalds 		/* open fileset secondary inode allocation map */
181*1da177e4SLinus Torvalds 		rc = -EIO;
182*1da177e4SLinus Torvalds 		goto errout40;
183*1da177e4SLinus Torvalds 	}
184*1da177e4SLinus Torvalds 	jfs_info("jfs_mount: ipimap:0x%p", ipimap);
185*1da177e4SLinus Torvalds 
186*1da177e4SLinus Torvalds 	/* map further access of per fileset inodes by the fileset inode */
187*1da177e4SLinus Torvalds 	sbi->ipimap = ipimap;
188*1da177e4SLinus Torvalds 
189*1da177e4SLinus Torvalds 	/* initialize fileset inode allocation map */
190*1da177e4SLinus Torvalds 	if ((rc = diMount(ipimap))) {
191*1da177e4SLinus Torvalds 		jfs_err("jfs_mount: diMount failed w/rc = %d", rc);
192*1da177e4SLinus Torvalds 		goto errout41;
193*1da177e4SLinus Torvalds 	}
194*1da177e4SLinus Torvalds 
195*1da177e4SLinus Torvalds 	goto out;
196*1da177e4SLinus Torvalds 
197*1da177e4SLinus Torvalds 	/*
198*1da177e4SLinus Torvalds 	 *      unwind on error
199*1da177e4SLinus Torvalds 	 */
200*1da177e4SLinus Torvalds       errout41:		/* close fileset inode allocation map inode */
201*1da177e4SLinus Torvalds 	diFreeSpecial(ipimap);
202*1da177e4SLinus Torvalds 
203*1da177e4SLinus Torvalds       errout40:		/* fileset closed */
204*1da177e4SLinus Torvalds 
205*1da177e4SLinus Torvalds 	/* close secondary aggregate inode allocation map */
206*1da177e4SLinus Torvalds 	if (ipaimap2) {
207*1da177e4SLinus Torvalds 		diUnmount(ipaimap2, 1);
208*1da177e4SLinus Torvalds 		diFreeSpecial(ipaimap2);
209*1da177e4SLinus Torvalds 	}
210*1da177e4SLinus Torvalds 
211*1da177e4SLinus Torvalds       errout35:
212*1da177e4SLinus Torvalds 
213*1da177e4SLinus Torvalds 	/* close aggregate block allocation map */
214*1da177e4SLinus Torvalds 	dbUnmount(ipbmap, 1);
215*1da177e4SLinus Torvalds 	diFreeSpecial(ipbmap);
216*1da177e4SLinus Torvalds 
217*1da177e4SLinus Torvalds       errout22:		/* close aggregate inode allocation map */
218*1da177e4SLinus Torvalds 
219*1da177e4SLinus Torvalds 	diUnmount(ipaimap, 1);
220*1da177e4SLinus Torvalds 
221*1da177e4SLinus Torvalds       errout21:		/* close aggregate inodes */
222*1da177e4SLinus Torvalds 	diFreeSpecial(ipaimap);
223*1da177e4SLinus Torvalds       errout20:		/* aggregate closed */
224*1da177e4SLinus Torvalds 
225*1da177e4SLinus Torvalds       out:
226*1da177e4SLinus Torvalds 
227*1da177e4SLinus Torvalds 	if (rc)
228*1da177e4SLinus Torvalds 		jfs_err("Mount JFS Failure: %d", rc);
229*1da177e4SLinus Torvalds 
230*1da177e4SLinus Torvalds 	return rc;
231*1da177e4SLinus Torvalds }
232*1da177e4SLinus Torvalds 
233*1da177e4SLinus Torvalds /*
234*1da177e4SLinus Torvalds  * NAME:	jfs_mount_rw(sb, remount)
235*1da177e4SLinus Torvalds  *
236*1da177e4SLinus Torvalds  * FUNCTION:	Completes read-write mount, or remounts read-only volume
237*1da177e4SLinus Torvalds  *		as read-write
238*1da177e4SLinus Torvalds  */
239*1da177e4SLinus Torvalds int jfs_mount_rw(struct super_block *sb, int remount)
240*1da177e4SLinus Torvalds {
241*1da177e4SLinus Torvalds 	struct jfs_sb_info *sbi = JFS_SBI(sb);
242*1da177e4SLinus Torvalds 	int rc;
243*1da177e4SLinus Torvalds 
244*1da177e4SLinus Torvalds 	/*
245*1da177e4SLinus Torvalds 	 * If we are re-mounting a previously read-only volume, we want to
246*1da177e4SLinus Torvalds 	 * re-read the inode and block maps, since fsck.jfs may have updated
247*1da177e4SLinus Torvalds 	 * them.
248*1da177e4SLinus Torvalds 	 */
249*1da177e4SLinus Torvalds 	if (remount) {
250*1da177e4SLinus Torvalds 		if (chkSuper(sb) || (sbi->state != FM_CLEAN))
251*1da177e4SLinus Torvalds 			return -EINVAL;
252*1da177e4SLinus Torvalds 
253*1da177e4SLinus Torvalds 		truncate_inode_pages(sbi->ipimap->i_mapping, 0);
254*1da177e4SLinus Torvalds 		truncate_inode_pages(sbi->ipbmap->i_mapping, 0);
255*1da177e4SLinus Torvalds 		diUnmount(sbi->ipimap, 1);
256*1da177e4SLinus Torvalds 		if ((rc = diMount(sbi->ipimap))) {
257*1da177e4SLinus Torvalds 			jfs_err("jfs_mount_rw: diMount failed!");
258*1da177e4SLinus Torvalds 			return rc;
259*1da177e4SLinus Torvalds 		}
260*1da177e4SLinus Torvalds 
261*1da177e4SLinus Torvalds 		dbUnmount(sbi->ipbmap, 1);
262*1da177e4SLinus Torvalds 		if ((rc = dbMount(sbi->ipbmap))) {
263*1da177e4SLinus Torvalds 			jfs_err("jfs_mount_rw: dbMount failed!");
264*1da177e4SLinus Torvalds 			return rc;
265*1da177e4SLinus Torvalds 		}
266*1da177e4SLinus Torvalds 	}
267*1da177e4SLinus Torvalds 
268*1da177e4SLinus Torvalds 	/*
269*1da177e4SLinus Torvalds 	 * open/initialize log
270*1da177e4SLinus Torvalds 	 */
271*1da177e4SLinus Torvalds 	if ((rc = lmLogOpen(sb)))
272*1da177e4SLinus Torvalds 		return rc;
273*1da177e4SLinus Torvalds 
274*1da177e4SLinus Torvalds 	/*
275*1da177e4SLinus Torvalds 	 * update file system superblock;
276*1da177e4SLinus Torvalds 	 */
277*1da177e4SLinus Torvalds 	if ((rc = updateSuper(sb, FM_MOUNT))) {
278*1da177e4SLinus Torvalds 		jfs_err("jfs_mount: updateSuper failed w/rc = %d", rc);
279*1da177e4SLinus Torvalds 		lmLogClose(sb);
280*1da177e4SLinus Torvalds 		return rc;
281*1da177e4SLinus Torvalds 	}
282*1da177e4SLinus Torvalds 
283*1da177e4SLinus Torvalds 	/*
284*1da177e4SLinus Torvalds 	 * write MOUNT log record of the file system
285*1da177e4SLinus Torvalds 	 */
286*1da177e4SLinus Torvalds 	logMOUNT(sb);
287*1da177e4SLinus Torvalds 
288*1da177e4SLinus Torvalds 	/*
289*1da177e4SLinus Torvalds 	 * Set page cache allocation policy
290*1da177e4SLinus Torvalds 	 */
291*1da177e4SLinus Torvalds 	mapping_set_gfp_mask(sb->s_bdev->bd_inode->i_mapping, GFP_NOFS);
292*1da177e4SLinus Torvalds 
293*1da177e4SLinus Torvalds 	return rc;
294*1da177e4SLinus Torvalds }
295*1da177e4SLinus Torvalds 
296*1da177e4SLinus Torvalds /*
297*1da177e4SLinus Torvalds  *	chkSuper()
298*1da177e4SLinus Torvalds  *
299*1da177e4SLinus Torvalds  * validate the superblock of the file system to be mounted and
300*1da177e4SLinus Torvalds  * get the file system parameters.
301*1da177e4SLinus Torvalds  *
302*1da177e4SLinus Torvalds  * returns
303*1da177e4SLinus Torvalds  *	0 with fragsize set if check successful
304*1da177e4SLinus Torvalds  *	error code if not successful
305*1da177e4SLinus Torvalds  */
306*1da177e4SLinus Torvalds static int chkSuper(struct super_block *sb)
307*1da177e4SLinus Torvalds {
308*1da177e4SLinus Torvalds 	int rc = 0;
309*1da177e4SLinus Torvalds 	struct jfs_sb_info *sbi = JFS_SBI(sb);
310*1da177e4SLinus Torvalds 	struct jfs_superblock *j_sb;
311*1da177e4SLinus Torvalds 	struct buffer_head *bh;
312*1da177e4SLinus Torvalds 	int AIM_bytesize, AIT_bytesize;
313*1da177e4SLinus Torvalds 	int expected_AIM_bytesize, expected_AIT_bytesize;
314*1da177e4SLinus Torvalds 	s64 AIM_byte_addr, AIT_byte_addr, fsckwsp_addr;
315*1da177e4SLinus Torvalds 	s64 byte_addr_diff0, byte_addr_diff1;
316*1da177e4SLinus Torvalds 	s32 bsize;
317*1da177e4SLinus Torvalds 
318*1da177e4SLinus Torvalds 	if ((rc = readSuper(sb, &bh)))
319*1da177e4SLinus Torvalds 		return rc;
320*1da177e4SLinus Torvalds 	j_sb = (struct jfs_superblock *)bh->b_data;
321*1da177e4SLinus Torvalds 
322*1da177e4SLinus Torvalds 	/*
323*1da177e4SLinus Torvalds 	 * validate superblock
324*1da177e4SLinus Torvalds 	 */
325*1da177e4SLinus Torvalds 	/* validate fs signature */
326*1da177e4SLinus Torvalds 	if (strncmp(j_sb->s_magic, JFS_MAGIC, 4) ||
327*1da177e4SLinus Torvalds 	    le32_to_cpu(j_sb->s_version) > JFS_VERSION) {
328*1da177e4SLinus Torvalds 		rc = -EINVAL;
329*1da177e4SLinus Torvalds 		goto out;
330*1da177e4SLinus Torvalds 	}
331*1da177e4SLinus Torvalds 
332*1da177e4SLinus Torvalds 	bsize = le32_to_cpu(j_sb->s_bsize);
333*1da177e4SLinus Torvalds #ifdef _JFS_4K
334*1da177e4SLinus Torvalds 	if (bsize != PSIZE) {
335*1da177e4SLinus Torvalds 		jfs_err("Currently only 4K block size supported!");
336*1da177e4SLinus Torvalds 		rc = -EINVAL;
337*1da177e4SLinus Torvalds 		goto out;
338*1da177e4SLinus Torvalds 	}
339*1da177e4SLinus Torvalds #endif				/* _JFS_4K */
340*1da177e4SLinus Torvalds 
341*1da177e4SLinus Torvalds 	jfs_info("superblock: flag:0x%08x state:0x%08x size:0x%Lx",
342*1da177e4SLinus Torvalds 		 le32_to_cpu(j_sb->s_flag), le32_to_cpu(j_sb->s_state),
343*1da177e4SLinus Torvalds 		 (unsigned long long) le64_to_cpu(j_sb->s_size));
344*1da177e4SLinus Torvalds 
345*1da177e4SLinus Torvalds 	/* validate the descriptors for Secondary AIM and AIT */
346*1da177e4SLinus Torvalds 	if ((j_sb->s_flag & cpu_to_le32(JFS_BAD_SAIT)) !=
347*1da177e4SLinus Torvalds 	    cpu_to_le32(JFS_BAD_SAIT)) {
348*1da177e4SLinus Torvalds 		expected_AIM_bytesize = 2 * PSIZE;
349*1da177e4SLinus Torvalds 		AIM_bytesize = lengthPXD(&(j_sb->s_aim2)) * bsize;
350*1da177e4SLinus Torvalds 		expected_AIT_bytesize = 4 * PSIZE;
351*1da177e4SLinus Torvalds 		AIT_bytesize = lengthPXD(&(j_sb->s_ait2)) * bsize;
352*1da177e4SLinus Torvalds 		AIM_byte_addr = addressPXD(&(j_sb->s_aim2)) * bsize;
353*1da177e4SLinus Torvalds 		AIT_byte_addr = addressPXD(&(j_sb->s_ait2)) * bsize;
354*1da177e4SLinus Torvalds 		byte_addr_diff0 = AIT_byte_addr - AIM_byte_addr;
355*1da177e4SLinus Torvalds 		fsckwsp_addr = addressPXD(&(j_sb->s_fsckpxd)) * bsize;
356*1da177e4SLinus Torvalds 		byte_addr_diff1 = fsckwsp_addr - AIT_byte_addr;
357*1da177e4SLinus Torvalds 		if ((AIM_bytesize != expected_AIM_bytesize) ||
358*1da177e4SLinus Torvalds 		    (AIT_bytesize != expected_AIT_bytesize) ||
359*1da177e4SLinus Torvalds 		    (byte_addr_diff0 != AIM_bytesize) ||
360*1da177e4SLinus Torvalds 		    (byte_addr_diff1 <= AIT_bytesize))
361*1da177e4SLinus Torvalds 			j_sb->s_flag |= cpu_to_le32(JFS_BAD_SAIT);
362*1da177e4SLinus Torvalds 	}
363*1da177e4SLinus Torvalds 
364*1da177e4SLinus Torvalds 	if ((j_sb->s_flag & cpu_to_le32(JFS_GROUPCOMMIT)) !=
365*1da177e4SLinus Torvalds 	    cpu_to_le32(JFS_GROUPCOMMIT))
366*1da177e4SLinus Torvalds 		j_sb->s_flag |= cpu_to_le32(JFS_GROUPCOMMIT);
367*1da177e4SLinus Torvalds 
368*1da177e4SLinus Torvalds 	/* validate fs state */
369*1da177e4SLinus Torvalds 	if (j_sb->s_state != cpu_to_le32(FM_CLEAN) &&
370*1da177e4SLinus Torvalds 	    !(sb->s_flags & MS_RDONLY)) {
371*1da177e4SLinus Torvalds 		jfs_err("jfs_mount: Mount Failure: File System Dirty.");
372*1da177e4SLinus Torvalds 		rc = -EINVAL;
373*1da177e4SLinus Torvalds 		goto out;
374*1da177e4SLinus Torvalds 	}
375*1da177e4SLinus Torvalds 
376*1da177e4SLinus Torvalds 	sbi->state = le32_to_cpu(j_sb->s_state);
377*1da177e4SLinus Torvalds 	sbi->mntflag = le32_to_cpu(j_sb->s_flag);
378*1da177e4SLinus Torvalds 
379*1da177e4SLinus Torvalds 	/*
380*1da177e4SLinus Torvalds 	 * JFS always does I/O by 4K pages.  Don't tell the buffer cache
381*1da177e4SLinus Torvalds 	 * that we use anything else (leave s_blocksize alone).
382*1da177e4SLinus Torvalds 	 */
383*1da177e4SLinus Torvalds 	sbi->bsize = bsize;
384*1da177e4SLinus Torvalds 	sbi->l2bsize = le16_to_cpu(j_sb->s_l2bsize);
385*1da177e4SLinus Torvalds 
386*1da177e4SLinus Torvalds 	/*
387*1da177e4SLinus Torvalds 	 * For now, ignore s_pbsize, l2bfactor.  All I/O going through buffer
388*1da177e4SLinus Torvalds 	 * cache.
389*1da177e4SLinus Torvalds 	 */
390*1da177e4SLinus Torvalds 	sbi->nbperpage = PSIZE >> sbi->l2bsize;
391*1da177e4SLinus Torvalds 	sbi->l2nbperpage = L2PSIZE - sbi->l2bsize;
392*1da177e4SLinus Torvalds 	sbi->l2niperblk = sbi->l2bsize - L2DISIZE;
393*1da177e4SLinus Torvalds 	if (sbi->mntflag & JFS_INLINELOG)
394*1da177e4SLinus Torvalds 		sbi->logpxd = j_sb->s_logpxd;
395*1da177e4SLinus Torvalds 	else {
396*1da177e4SLinus Torvalds 		sbi->logdev = new_decode_dev(le32_to_cpu(j_sb->s_logdev));
397*1da177e4SLinus Torvalds 		memcpy(sbi->uuid, j_sb->s_uuid, sizeof(sbi->uuid));
398*1da177e4SLinus Torvalds 		memcpy(sbi->loguuid, j_sb->s_loguuid, sizeof(sbi->uuid));
399*1da177e4SLinus Torvalds 	}
400*1da177e4SLinus Torvalds 	sbi->fsckpxd = j_sb->s_fsckpxd;
401*1da177e4SLinus Torvalds 	sbi->ait2 = j_sb->s_ait2;
402*1da177e4SLinus Torvalds 
403*1da177e4SLinus Torvalds       out:
404*1da177e4SLinus Torvalds 	brelse(bh);
405*1da177e4SLinus Torvalds 	return rc;
406*1da177e4SLinus Torvalds }
407*1da177e4SLinus Torvalds 
408*1da177e4SLinus Torvalds 
409*1da177e4SLinus Torvalds /*
410*1da177e4SLinus Torvalds  *	updateSuper()
411*1da177e4SLinus Torvalds  *
412*1da177e4SLinus Torvalds  * update synchronously superblock if it is mounted read-write.
413*1da177e4SLinus Torvalds  */
414*1da177e4SLinus Torvalds int updateSuper(struct super_block *sb, uint state)
415*1da177e4SLinus Torvalds {
416*1da177e4SLinus Torvalds 	struct jfs_superblock *j_sb;
417*1da177e4SLinus Torvalds 	struct jfs_sb_info *sbi = JFS_SBI(sb);
418*1da177e4SLinus Torvalds 	struct buffer_head *bh;
419*1da177e4SLinus Torvalds 	int rc;
420*1da177e4SLinus Torvalds 
421*1da177e4SLinus Torvalds 	if (sbi->flag & JFS_NOINTEGRITY) {
422*1da177e4SLinus Torvalds 		if (state == FM_DIRTY) {
423*1da177e4SLinus Torvalds 			sbi->p_state = state;
424*1da177e4SLinus Torvalds 			return 0;
425*1da177e4SLinus Torvalds 		} else if (state == FM_MOUNT) {
426*1da177e4SLinus Torvalds 			sbi->p_state = sbi->state;
427*1da177e4SLinus Torvalds 			state = FM_DIRTY;
428*1da177e4SLinus Torvalds 		} else if (state == FM_CLEAN) {
429*1da177e4SLinus Torvalds 			state = sbi->p_state;
430*1da177e4SLinus Torvalds 		} else
431*1da177e4SLinus Torvalds 			jfs_err("updateSuper: bad state");
432*1da177e4SLinus Torvalds 	} else if (sbi->state == FM_DIRTY)
433*1da177e4SLinus Torvalds 		return 0;
434*1da177e4SLinus Torvalds 
435*1da177e4SLinus Torvalds 	if ((rc = readSuper(sb, &bh)))
436*1da177e4SLinus Torvalds 		return rc;
437*1da177e4SLinus Torvalds 
438*1da177e4SLinus Torvalds 	j_sb = (struct jfs_superblock *)bh->b_data;
439*1da177e4SLinus Torvalds 
440*1da177e4SLinus Torvalds 	j_sb->s_state = cpu_to_le32(state);
441*1da177e4SLinus Torvalds 	sbi->state = state;
442*1da177e4SLinus Torvalds 
443*1da177e4SLinus Torvalds 	if (state == FM_MOUNT) {
444*1da177e4SLinus Torvalds 		/* record log's dev_t and mount serial number */
445*1da177e4SLinus Torvalds 		j_sb->s_logdev = cpu_to_le32(new_encode_dev(sbi->log->bdev->bd_dev));
446*1da177e4SLinus Torvalds 		j_sb->s_logserial = cpu_to_le32(sbi->log->serial);
447*1da177e4SLinus Torvalds 	} else if (state == FM_CLEAN) {
448*1da177e4SLinus Torvalds 		/*
449*1da177e4SLinus Torvalds 		 * If this volume is shared with OS/2, OS/2 will need to
450*1da177e4SLinus Torvalds 		 * recalculate DASD usage, since we don't deal with it.
451*1da177e4SLinus Torvalds 		 */
452*1da177e4SLinus Torvalds 		if (j_sb->s_flag & cpu_to_le32(JFS_DASD_ENABLED))
453*1da177e4SLinus Torvalds 			j_sb->s_flag |= cpu_to_le32(JFS_DASD_PRIME);
454*1da177e4SLinus Torvalds 	}
455*1da177e4SLinus Torvalds 
456*1da177e4SLinus Torvalds 	mark_buffer_dirty(bh);
457*1da177e4SLinus Torvalds 	sync_dirty_buffer(bh);
458*1da177e4SLinus Torvalds 	brelse(bh);
459*1da177e4SLinus Torvalds 
460*1da177e4SLinus Torvalds 	return 0;
461*1da177e4SLinus Torvalds }
462*1da177e4SLinus Torvalds 
463*1da177e4SLinus Torvalds 
464*1da177e4SLinus Torvalds /*
465*1da177e4SLinus Torvalds  *	readSuper()
466*1da177e4SLinus Torvalds  *
467*1da177e4SLinus Torvalds  * read superblock by raw sector address
468*1da177e4SLinus Torvalds  */
469*1da177e4SLinus Torvalds int readSuper(struct super_block *sb, struct buffer_head **bpp)
470*1da177e4SLinus Torvalds {
471*1da177e4SLinus Torvalds 	/* read in primary superblock */
472*1da177e4SLinus Torvalds 	*bpp = sb_bread(sb, SUPER1_OFF >> sb->s_blocksize_bits);
473*1da177e4SLinus Torvalds 	if (*bpp)
474*1da177e4SLinus Torvalds 		return 0;
475*1da177e4SLinus Torvalds 
476*1da177e4SLinus Torvalds 	/* read in secondary/replicated superblock */
477*1da177e4SLinus Torvalds 	*bpp = sb_bread(sb, SUPER2_OFF >> sb->s_blocksize_bits);
478*1da177e4SLinus Torvalds 	if (*bpp)
479*1da177e4SLinus Torvalds 		return 0;
480*1da177e4SLinus Torvalds 
481*1da177e4SLinus Torvalds 	return -EIO;
482*1da177e4SLinus Torvalds }
483*1da177e4SLinus Torvalds 
484*1da177e4SLinus Torvalds 
485*1da177e4SLinus Torvalds /*
486*1da177e4SLinus Torvalds  *	logMOUNT()
487*1da177e4SLinus Torvalds  *
488*1da177e4SLinus Torvalds  * function: write a MOUNT log record for file system.
489*1da177e4SLinus Torvalds  *
490*1da177e4SLinus Torvalds  * MOUNT record keeps logredo() from processing log records
491*1da177e4SLinus Torvalds  * for this file system past this point in log.
492*1da177e4SLinus Torvalds  * it is harmless if mount fails.
493*1da177e4SLinus Torvalds  *
494*1da177e4SLinus Torvalds  * note: MOUNT record is at aggregate level, not at fileset level,
495*1da177e4SLinus Torvalds  * since log records of previous mounts of a fileset
496*1da177e4SLinus Torvalds  * (e.g., AFTER record of extent allocation) have to be processed
497*1da177e4SLinus Torvalds  * to update block allocation map at aggregate level.
498*1da177e4SLinus Torvalds  */
499*1da177e4SLinus Torvalds static int logMOUNT(struct super_block *sb)
500*1da177e4SLinus Torvalds {
501*1da177e4SLinus Torvalds 	struct jfs_log *log = JFS_SBI(sb)->log;
502*1da177e4SLinus Torvalds 	struct lrd lrd;
503*1da177e4SLinus Torvalds 
504*1da177e4SLinus Torvalds 	lrd.logtid = 0;
505*1da177e4SLinus Torvalds 	lrd.backchain = 0;
506*1da177e4SLinus Torvalds 	lrd.type = cpu_to_le16(LOG_MOUNT);
507*1da177e4SLinus Torvalds 	lrd.length = 0;
508*1da177e4SLinus Torvalds 	lrd.aggregate = cpu_to_le32(new_encode_dev(sb->s_bdev->bd_dev));
509*1da177e4SLinus Torvalds 	lmLog(log, NULL, &lrd, NULL);
510*1da177e4SLinus Torvalds 
511*1da177e4SLinus Torvalds 	return 0;
512*1da177e4SLinus Torvalds }
513