162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *   Copyright (C) International Business Machines Corp., 2000-2004
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci/*
762306a36Sopenharmony_ci * Module: jfs_mount.c
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * note: file system in transition to aggregate/fileset:
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * file system mount is interpreted as the mount of aggregate,
1262306a36Sopenharmony_ci * if not already mounted, and mount of the single/only fileset in
1362306a36Sopenharmony_ci * the aggregate;
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci * a file system/aggregate is represented by an internal inode
1662306a36Sopenharmony_ci * (aka mount inode) initialized with aggregate superblock;
1762306a36Sopenharmony_ci * each vfs represents a fileset, and points to its "fileset inode
1862306a36Sopenharmony_ci * allocation map inode" (aka fileset inode):
1962306a36Sopenharmony_ci * (an aggregate itself is structured recursively as a filset:
2062306a36Sopenharmony_ci * an internal vfs is constructed and points to its "fileset inode
2162306a36Sopenharmony_ci * allocation map inode" (aka aggregate inode) where each inode
2262306a36Sopenharmony_ci * represents a fileset inode) so that inode number is mapped to
2362306a36Sopenharmony_ci * on-disk inode in uniform way at both aggregate and fileset level;
2462306a36Sopenharmony_ci *
2562306a36Sopenharmony_ci * each vnode/inode of a fileset is linked to its vfs (to facilitate
2662306a36Sopenharmony_ci * per fileset inode operations, e.g., unmount of a fileset, etc.);
2762306a36Sopenharmony_ci * each inode points to the mount inode (to facilitate access to
2862306a36Sopenharmony_ci * per aggregate information, e.g., block size, etc.) as well as
2962306a36Sopenharmony_ci * its file set inode.
3062306a36Sopenharmony_ci *
3162306a36Sopenharmony_ci *   aggregate
3262306a36Sopenharmony_ci *   ipmnt
3362306a36Sopenharmony_ci *   mntvfs -> fileset ipimap+ -> aggregate ipbmap -> aggregate ipaimap;
3462306a36Sopenharmony_ci *             fileset vfs     -> vp(1) <-> ... <-> vp(n) <->vproot;
3562306a36Sopenharmony_ci */
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#include <linux/fs.h>
3862306a36Sopenharmony_ci#include <linux/buffer_head.h>
3962306a36Sopenharmony_ci#include <linux/blkdev.h>
4062306a36Sopenharmony_ci#include <linux/log2.h>
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#include "jfs_incore.h"
4362306a36Sopenharmony_ci#include "jfs_filsys.h"
4462306a36Sopenharmony_ci#include "jfs_superblock.h"
4562306a36Sopenharmony_ci#include "jfs_dmap.h"
4662306a36Sopenharmony_ci#include "jfs_imap.h"
4762306a36Sopenharmony_ci#include "jfs_metapage.h"
4862306a36Sopenharmony_ci#include "jfs_debug.h"
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci/*
5262306a36Sopenharmony_ci * forward references
5362306a36Sopenharmony_ci */
5462306a36Sopenharmony_cistatic int chkSuper(struct super_block *);
5562306a36Sopenharmony_cistatic int logMOUNT(struct super_block *sb);
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci/*
5862306a36Sopenharmony_ci * NAME:	jfs_mount(sb)
5962306a36Sopenharmony_ci *
6062306a36Sopenharmony_ci * FUNCTION:	vfs_mount()
6162306a36Sopenharmony_ci *
6262306a36Sopenharmony_ci * PARAMETER:	sb	- super block
6362306a36Sopenharmony_ci *
6462306a36Sopenharmony_ci * RETURN:	-EBUSY	- device already mounted or open for write
6562306a36Sopenharmony_ci *		-EBUSY	- cvrdvp already mounted;
6662306a36Sopenharmony_ci *		-EBUSY	- mount table full
6762306a36Sopenharmony_ci *		-ENOTDIR- cvrdvp not directory on a device mount
6862306a36Sopenharmony_ci *		-ENXIO	- device open failure
6962306a36Sopenharmony_ci */
7062306a36Sopenharmony_ciint jfs_mount(struct super_block *sb)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	int rc = 0;		/* Return code */
7362306a36Sopenharmony_ci	struct jfs_sb_info *sbi = JFS_SBI(sb);
7462306a36Sopenharmony_ci	struct inode *ipaimap = NULL;
7562306a36Sopenharmony_ci	struct inode *ipaimap2 = NULL;
7662306a36Sopenharmony_ci	struct inode *ipimap = NULL;
7762306a36Sopenharmony_ci	struct inode *ipbmap = NULL;
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	/*
8062306a36Sopenharmony_ci	 * read/validate superblock
8162306a36Sopenharmony_ci	 * (initialize mount inode from the superblock)
8262306a36Sopenharmony_ci	 */
8362306a36Sopenharmony_ci	if ((rc = chkSuper(sb))) {
8462306a36Sopenharmony_ci		goto out;
8562306a36Sopenharmony_ci	}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	ipaimap = diReadSpecial(sb, AGGREGATE_I, 0);
8862306a36Sopenharmony_ci	if (ipaimap == NULL) {
8962306a36Sopenharmony_ci		jfs_err("jfs_mount: Failed to read AGGREGATE_I");
9062306a36Sopenharmony_ci		rc = -EIO;
9162306a36Sopenharmony_ci		goto out;
9262306a36Sopenharmony_ci	}
9362306a36Sopenharmony_ci	sbi->ipaimap = ipaimap;
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	jfs_info("jfs_mount: ipaimap:0x%p", ipaimap);
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	/*
9862306a36Sopenharmony_ci	 * initialize aggregate inode allocation map
9962306a36Sopenharmony_ci	 */
10062306a36Sopenharmony_ci	if ((rc = diMount(ipaimap))) {
10162306a36Sopenharmony_ci		jfs_err("jfs_mount: diMount(ipaimap) failed w/rc = %d", rc);
10262306a36Sopenharmony_ci		goto err_ipaimap;
10362306a36Sopenharmony_ci	}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	/*
10662306a36Sopenharmony_ci	 * open aggregate block allocation map
10762306a36Sopenharmony_ci	 */
10862306a36Sopenharmony_ci	ipbmap = diReadSpecial(sb, BMAP_I, 0);
10962306a36Sopenharmony_ci	if (ipbmap == NULL) {
11062306a36Sopenharmony_ci		rc = -EIO;
11162306a36Sopenharmony_ci		goto err_umount_ipaimap;
11262306a36Sopenharmony_ci	}
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	jfs_info("jfs_mount: ipbmap:0x%p", ipbmap);
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	sbi->ipbmap = ipbmap;
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	/*
11962306a36Sopenharmony_ci	 * initialize aggregate block allocation map
12062306a36Sopenharmony_ci	 */
12162306a36Sopenharmony_ci	if ((rc = dbMount(ipbmap))) {
12262306a36Sopenharmony_ci		jfs_err("jfs_mount: dbMount failed w/rc = %d", rc);
12362306a36Sopenharmony_ci		goto err_ipbmap;
12462306a36Sopenharmony_ci	}
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	/*
12762306a36Sopenharmony_ci	 * open the secondary aggregate inode allocation map
12862306a36Sopenharmony_ci	 *
12962306a36Sopenharmony_ci	 * This is a duplicate of the aggregate inode allocation map.
13062306a36Sopenharmony_ci	 *
13162306a36Sopenharmony_ci	 * hand craft a vfs in the same fashion as we did to read ipaimap.
13262306a36Sopenharmony_ci	 * By adding INOSPEREXT (32) to the inode number, we are telling
13362306a36Sopenharmony_ci	 * diReadSpecial that we are reading from the secondary aggregate
13462306a36Sopenharmony_ci	 * inode table.  This also creates a unique entry in the inode hash
13562306a36Sopenharmony_ci	 * table.
13662306a36Sopenharmony_ci	 */
13762306a36Sopenharmony_ci	if ((sbi->mntflag & JFS_BAD_SAIT) == 0) {
13862306a36Sopenharmony_ci		ipaimap2 = diReadSpecial(sb, AGGREGATE_I, 1);
13962306a36Sopenharmony_ci		if (!ipaimap2) {
14062306a36Sopenharmony_ci			jfs_err("jfs_mount: Failed to read AGGREGATE_I");
14162306a36Sopenharmony_ci			rc = -EIO;
14262306a36Sopenharmony_ci			goto err_umount_ipbmap;
14362306a36Sopenharmony_ci		}
14462306a36Sopenharmony_ci		sbi->ipaimap2 = ipaimap2;
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci		jfs_info("jfs_mount: ipaimap2:0x%p", ipaimap2);
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci		/*
14962306a36Sopenharmony_ci		 * initialize secondary aggregate inode allocation map
15062306a36Sopenharmony_ci		 */
15162306a36Sopenharmony_ci		if ((rc = diMount(ipaimap2))) {
15262306a36Sopenharmony_ci			jfs_err("jfs_mount: diMount(ipaimap2) failed, rc = %d",
15362306a36Sopenharmony_ci				rc);
15462306a36Sopenharmony_ci			goto err_ipaimap2;
15562306a36Sopenharmony_ci		}
15662306a36Sopenharmony_ci	} else
15762306a36Sopenharmony_ci		/* Secondary aggregate inode table is not valid */
15862306a36Sopenharmony_ci		sbi->ipaimap2 = NULL;
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	/*
16162306a36Sopenharmony_ci	 *	mount (the only/single) fileset
16262306a36Sopenharmony_ci	 */
16362306a36Sopenharmony_ci	/*
16462306a36Sopenharmony_ci	 * open fileset inode allocation map (aka fileset inode)
16562306a36Sopenharmony_ci	 */
16662306a36Sopenharmony_ci	ipimap = diReadSpecial(sb, FILESYSTEM_I, 0);
16762306a36Sopenharmony_ci	if (ipimap == NULL) {
16862306a36Sopenharmony_ci		jfs_err("jfs_mount: Failed to read FILESYSTEM_I");
16962306a36Sopenharmony_ci		/* open fileset secondary inode allocation map */
17062306a36Sopenharmony_ci		rc = -EIO;
17162306a36Sopenharmony_ci		goto err_umount_ipaimap2;
17262306a36Sopenharmony_ci	}
17362306a36Sopenharmony_ci	jfs_info("jfs_mount: ipimap:0x%p", ipimap);
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	/* initialize fileset inode allocation map */
17662306a36Sopenharmony_ci	if ((rc = diMount(ipimap))) {
17762306a36Sopenharmony_ci		jfs_err("jfs_mount: diMount failed w/rc = %d", rc);
17862306a36Sopenharmony_ci		goto err_ipimap;
17962306a36Sopenharmony_ci	}
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	/* map further access of per fileset inodes by the fileset inode */
18262306a36Sopenharmony_ci	sbi->ipimap = ipimap;
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	return rc;
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	/*
18762306a36Sopenharmony_ci	 *	unwind on error
18862306a36Sopenharmony_ci	 */
18962306a36Sopenharmony_cierr_ipimap:
19062306a36Sopenharmony_ci	/* close fileset inode allocation map inode */
19162306a36Sopenharmony_ci	diFreeSpecial(ipimap);
19262306a36Sopenharmony_cierr_umount_ipaimap2:
19362306a36Sopenharmony_ci	/* close secondary aggregate inode allocation map */
19462306a36Sopenharmony_ci	if (ipaimap2)
19562306a36Sopenharmony_ci		diUnmount(ipaimap2, 1);
19662306a36Sopenharmony_cierr_ipaimap2:
19762306a36Sopenharmony_ci	/* close aggregate inodes */
19862306a36Sopenharmony_ci	if (ipaimap2)
19962306a36Sopenharmony_ci		diFreeSpecial(ipaimap2);
20062306a36Sopenharmony_cierr_umount_ipbmap:	/* close aggregate block allocation map */
20162306a36Sopenharmony_ci	dbUnmount(ipbmap, 1);
20262306a36Sopenharmony_cierr_ipbmap:		/* close aggregate inodes */
20362306a36Sopenharmony_ci	diFreeSpecial(ipbmap);
20462306a36Sopenharmony_cierr_umount_ipaimap:	/* close aggregate inode allocation map */
20562306a36Sopenharmony_ci	diUnmount(ipaimap, 1);
20662306a36Sopenharmony_cierr_ipaimap:		/* close aggregate inodes */
20762306a36Sopenharmony_ci	diFreeSpecial(ipaimap);
20862306a36Sopenharmony_ciout:
20962306a36Sopenharmony_ci	if (rc)
21062306a36Sopenharmony_ci		jfs_err("Mount JFS Failure: %d", rc);
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	return rc;
21362306a36Sopenharmony_ci}
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci/*
21662306a36Sopenharmony_ci * NAME:	jfs_mount_rw(sb, remount)
21762306a36Sopenharmony_ci *
21862306a36Sopenharmony_ci * FUNCTION:	Completes read-write mount, or remounts read-only volume
21962306a36Sopenharmony_ci *		as read-write
22062306a36Sopenharmony_ci */
22162306a36Sopenharmony_ciint jfs_mount_rw(struct super_block *sb, int remount)
22262306a36Sopenharmony_ci{
22362306a36Sopenharmony_ci	struct jfs_sb_info *sbi = JFS_SBI(sb);
22462306a36Sopenharmony_ci	int rc;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	/*
22762306a36Sopenharmony_ci	 * If we are re-mounting a previously read-only volume, we want to
22862306a36Sopenharmony_ci	 * re-read the inode and block maps, since fsck.jfs may have updated
22962306a36Sopenharmony_ci	 * them.
23062306a36Sopenharmony_ci	 */
23162306a36Sopenharmony_ci	if (remount) {
23262306a36Sopenharmony_ci		if (chkSuper(sb) || (sbi->state != FM_CLEAN))
23362306a36Sopenharmony_ci			return -EINVAL;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci		truncate_inode_pages(sbi->ipimap->i_mapping, 0);
23662306a36Sopenharmony_ci		truncate_inode_pages(sbi->ipbmap->i_mapping, 0);
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci		IWRITE_LOCK(sbi->ipimap, RDWRLOCK_IMAP);
23962306a36Sopenharmony_ci		diUnmount(sbi->ipimap, 1);
24062306a36Sopenharmony_ci		if ((rc = diMount(sbi->ipimap))) {
24162306a36Sopenharmony_ci			IWRITE_UNLOCK(sbi->ipimap);
24262306a36Sopenharmony_ci			jfs_err("jfs_mount_rw: diMount failed!");
24362306a36Sopenharmony_ci			return rc;
24462306a36Sopenharmony_ci		}
24562306a36Sopenharmony_ci		IWRITE_UNLOCK(sbi->ipimap);
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci		dbUnmount(sbi->ipbmap, 1);
24862306a36Sopenharmony_ci		if ((rc = dbMount(sbi->ipbmap))) {
24962306a36Sopenharmony_ci			jfs_err("jfs_mount_rw: dbMount failed!");
25062306a36Sopenharmony_ci			return rc;
25162306a36Sopenharmony_ci		}
25262306a36Sopenharmony_ci	}
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	/*
25562306a36Sopenharmony_ci	 * open/initialize log
25662306a36Sopenharmony_ci	 */
25762306a36Sopenharmony_ci	if ((rc = lmLogOpen(sb)))
25862306a36Sopenharmony_ci		return rc;
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	/*
26162306a36Sopenharmony_ci	 * update file system superblock;
26262306a36Sopenharmony_ci	 */
26362306a36Sopenharmony_ci	if ((rc = updateSuper(sb, FM_MOUNT))) {
26462306a36Sopenharmony_ci		jfs_err("jfs_mount: updateSuper failed w/rc = %d", rc);
26562306a36Sopenharmony_ci		lmLogClose(sb);
26662306a36Sopenharmony_ci		return rc;
26762306a36Sopenharmony_ci	}
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	/*
27062306a36Sopenharmony_ci	 * write MOUNT log record of the file system
27162306a36Sopenharmony_ci	 */
27262306a36Sopenharmony_ci	logMOUNT(sb);
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	return rc;
27562306a36Sopenharmony_ci}
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci/*
27862306a36Sopenharmony_ci *	chkSuper()
27962306a36Sopenharmony_ci *
28062306a36Sopenharmony_ci * validate the superblock of the file system to be mounted and
28162306a36Sopenharmony_ci * get the file system parameters.
28262306a36Sopenharmony_ci *
28362306a36Sopenharmony_ci * returns
28462306a36Sopenharmony_ci *	0 with fragsize set if check successful
28562306a36Sopenharmony_ci *	error code if not successful
28662306a36Sopenharmony_ci */
28762306a36Sopenharmony_cistatic int chkSuper(struct super_block *sb)
28862306a36Sopenharmony_ci{
28962306a36Sopenharmony_ci	int rc = 0;
29062306a36Sopenharmony_ci	struct jfs_sb_info *sbi = JFS_SBI(sb);
29162306a36Sopenharmony_ci	struct jfs_superblock *j_sb;
29262306a36Sopenharmony_ci	struct buffer_head *bh;
29362306a36Sopenharmony_ci	int AIM_bytesize, AIT_bytesize;
29462306a36Sopenharmony_ci	int expected_AIM_bytesize, expected_AIT_bytesize;
29562306a36Sopenharmony_ci	s64 AIM_byte_addr, AIT_byte_addr, fsckwsp_addr;
29662306a36Sopenharmony_ci	s64 byte_addr_diff0, byte_addr_diff1;
29762306a36Sopenharmony_ci	s32 bsize;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	if ((rc = readSuper(sb, &bh)))
30062306a36Sopenharmony_ci		return rc;
30162306a36Sopenharmony_ci	j_sb = (struct jfs_superblock *)bh->b_data;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	/*
30462306a36Sopenharmony_ci	 * validate superblock
30562306a36Sopenharmony_ci	 */
30662306a36Sopenharmony_ci	/* validate fs signature */
30762306a36Sopenharmony_ci	if (strncmp(j_sb->s_magic, JFS_MAGIC, 4) ||
30862306a36Sopenharmony_ci	    le32_to_cpu(j_sb->s_version) > JFS_VERSION) {
30962306a36Sopenharmony_ci		rc = -EINVAL;
31062306a36Sopenharmony_ci		goto out;
31162306a36Sopenharmony_ci	}
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	bsize = le32_to_cpu(j_sb->s_bsize);
31462306a36Sopenharmony_ci	if (bsize != PSIZE) {
31562306a36Sopenharmony_ci		jfs_err("Only 4K block size supported!");
31662306a36Sopenharmony_ci		rc = -EINVAL;
31762306a36Sopenharmony_ci		goto out;
31862306a36Sopenharmony_ci	}
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	jfs_info("superblock: flag:0x%08x state:0x%08x size:0x%Lx",
32162306a36Sopenharmony_ci		 le32_to_cpu(j_sb->s_flag), le32_to_cpu(j_sb->s_state),
32262306a36Sopenharmony_ci		 (unsigned long long) le64_to_cpu(j_sb->s_size));
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	/* validate the descriptors for Secondary AIM and AIT */
32562306a36Sopenharmony_ci	if ((j_sb->s_flag & cpu_to_le32(JFS_BAD_SAIT)) !=
32662306a36Sopenharmony_ci	    cpu_to_le32(JFS_BAD_SAIT)) {
32762306a36Sopenharmony_ci		expected_AIM_bytesize = 2 * PSIZE;
32862306a36Sopenharmony_ci		AIM_bytesize = lengthPXD(&(j_sb->s_aim2)) * bsize;
32962306a36Sopenharmony_ci		expected_AIT_bytesize = 4 * PSIZE;
33062306a36Sopenharmony_ci		AIT_bytesize = lengthPXD(&(j_sb->s_ait2)) * bsize;
33162306a36Sopenharmony_ci		AIM_byte_addr = addressPXD(&(j_sb->s_aim2)) * bsize;
33262306a36Sopenharmony_ci		AIT_byte_addr = addressPXD(&(j_sb->s_ait2)) * bsize;
33362306a36Sopenharmony_ci		byte_addr_diff0 = AIT_byte_addr - AIM_byte_addr;
33462306a36Sopenharmony_ci		fsckwsp_addr = addressPXD(&(j_sb->s_fsckpxd)) * bsize;
33562306a36Sopenharmony_ci		byte_addr_diff1 = fsckwsp_addr - AIT_byte_addr;
33662306a36Sopenharmony_ci		if ((AIM_bytesize != expected_AIM_bytesize) ||
33762306a36Sopenharmony_ci		    (AIT_bytesize != expected_AIT_bytesize) ||
33862306a36Sopenharmony_ci		    (byte_addr_diff0 != AIM_bytesize) ||
33962306a36Sopenharmony_ci		    (byte_addr_diff1 <= AIT_bytesize))
34062306a36Sopenharmony_ci			j_sb->s_flag |= cpu_to_le32(JFS_BAD_SAIT);
34162306a36Sopenharmony_ci	}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	if ((j_sb->s_flag & cpu_to_le32(JFS_GROUPCOMMIT)) !=
34462306a36Sopenharmony_ci	    cpu_to_le32(JFS_GROUPCOMMIT))
34562306a36Sopenharmony_ci		j_sb->s_flag |= cpu_to_le32(JFS_GROUPCOMMIT);
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	/* validate fs state */
34862306a36Sopenharmony_ci	if (j_sb->s_state != cpu_to_le32(FM_CLEAN) &&
34962306a36Sopenharmony_ci	    !sb_rdonly(sb)) {
35062306a36Sopenharmony_ci		jfs_err("jfs_mount: Mount Failure: File System Dirty.");
35162306a36Sopenharmony_ci		rc = -EINVAL;
35262306a36Sopenharmony_ci		goto out;
35362306a36Sopenharmony_ci	}
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	sbi->state = le32_to_cpu(j_sb->s_state);
35662306a36Sopenharmony_ci	sbi->mntflag = le32_to_cpu(j_sb->s_flag);
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	/*
35962306a36Sopenharmony_ci	 * JFS always does I/O by 4K pages.  Don't tell the buffer cache
36062306a36Sopenharmony_ci	 * that we use anything else (leave s_blocksize alone).
36162306a36Sopenharmony_ci	 */
36262306a36Sopenharmony_ci	sbi->bsize = bsize;
36362306a36Sopenharmony_ci	sbi->l2bsize = le16_to_cpu(j_sb->s_l2bsize);
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci	/* check some fields for possible corruption */
36662306a36Sopenharmony_ci	if (sbi->l2bsize != ilog2((u32)bsize) ||
36762306a36Sopenharmony_ci	    j_sb->pad != 0 ||
36862306a36Sopenharmony_ci	    le32_to_cpu(j_sb->s_state) > FM_STATE_MAX) {
36962306a36Sopenharmony_ci		rc = -EINVAL;
37062306a36Sopenharmony_ci		jfs_err("jfs_mount: Mount Failure: superblock is corrupt!");
37162306a36Sopenharmony_ci		goto out;
37262306a36Sopenharmony_ci	}
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	/*
37562306a36Sopenharmony_ci	 * For now, ignore s_pbsize, l2bfactor.  All I/O going through buffer
37662306a36Sopenharmony_ci	 * cache.
37762306a36Sopenharmony_ci	 */
37862306a36Sopenharmony_ci	sbi->nbperpage = PSIZE >> sbi->l2bsize;
37962306a36Sopenharmony_ci	sbi->l2nbperpage = L2PSIZE - sbi->l2bsize;
38062306a36Sopenharmony_ci	sbi->l2niperblk = sbi->l2bsize - L2DISIZE;
38162306a36Sopenharmony_ci	if (sbi->mntflag & JFS_INLINELOG)
38262306a36Sopenharmony_ci		sbi->logpxd = j_sb->s_logpxd;
38362306a36Sopenharmony_ci	else {
38462306a36Sopenharmony_ci		sbi->logdev = new_decode_dev(le32_to_cpu(j_sb->s_logdev));
38562306a36Sopenharmony_ci		uuid_copy(&sbi->uuid, &j_sb->s_uuid);
38662306a36Sopenharmony_ci		uuid_copy(&sbi->loguuid, &j_sb->s_loguuid);
38762306a36Sopenharmony_ci	}
38862306a36Sopenharmony_ci	sbi->fsckpxd = j_sb->s_fsckpxd;
38962306a36Sopenharmony_ci	sbi->ait2 = j_sb->s_ait2;
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci      out:
39262306a36Sopenharmony_ci	brelse(bh);
39362306a36Sopenharmony_ci	return rc;
39462306a36Sopenharmony_ci}
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci/*
39862306a36Sopenharmony_ci *	updateSuper()
39962306a36Sopenharmony_ci *
40062306a36Sopenharmony_ci * update synchronously superblock if it is mounted read-write.
40162306a36Sopenharmony_ci */
40262306a36Sopenharmony_ciint updateSuper(struct super_block *sb, uint state)
40362306a36Sopenharmony_ci{
40462306a36Sopenharmony_ci	struct jfs_superblock *j_sb;
40562306a36Sopenharmony_ci	struct jfs_sb_info *sbi = JFS_SBI(sb);
40662306a36Sopenharmony_ci	struct buffer_head *bh;
40762306a36Sopenharmony_ci	int rc;
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	if (sbi->flag & JFS_NOINTEGRITY) {
41062306a36Sopenharmony_ci		if (state == FM_DIRTY) {
41162306a36Sopenharmony_ci			sbi->p_state = state;
41262306a36Sopenharmony_ci			return 0;
41362306a36Sopenharmony_ci		} else if (state == FM_MOUNT) {
41462306a36Sopenharmony_ci			sbi->p_state = sbi->state;
41562306a36Sopenharmony_ci			state = FM_DIRTY;
41662306a36Sopenharmony_ci		} else if (state == FM_CLEAN) {
41762306a36Sopenharmony_ci			state = sbi->p_state;
41862306a36Sopenharmony_ci		} else
41962306a36Sopenharmony_ci			jfs_err("updateSuper: bad state");
42062306a36Sopenharmony_ci	} else if (sbi->state == FM_DIRTY)
42162306a36Sopenharmony_ci		return 0;
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	if ((rc = readSuper(sb, &bh)))
42462306a36Sopenharmony_ci		return rc;
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	j_sb = (struct jfs_superblock *)bh->b_data;
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	j_sb->s_state = cpu_to_le32(state);
42962306a36Sopenharmony_ci	sbi->state = state;
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	if (state == FM_MOUNT) {
43262306a36Sopenharmony_ci		/* record log's dev_t and mount serial number */
43362306a36Sopenharmony_ci		j_sb->s_logdev = cpu_to_le32(new_encode_dev(sbi->log->bdev->bd_dev));
43462306a36Sopenharmony_ci		j_sb->s_logserial = cpu_to_le32(sbi->log->serial);
43562306a36Sopenharmony_ci	} else if (state == FM_CLEAN) {
43662306a36Sopenharmony_ci		/*
43762306a36Sopenharmony_ci		 * If this volume is shared with OS/2, OS/2 will need to
43862306a36Sopenharmony_ci		 * recalculate DASD usage, since we don't deal with it.
43962306a36Sopenharmony_ci		 */
44062306a36Sopenharmony_ci		if (j_sb->s_flag & cpu_to_le32(JFS_DASD_ENABLED))
44162306a36Sopenharmony_ci			j_sb->s_flag |= cpu_to_le32(JFS_DASD_PRIME);
44262306a36Sopenharmony_ci	}
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	mark_buffer_dirty(bh);
44562306a36Sopenharmony_ci	sync_dirty_buffer(bh);
44662306a36Sopenharmony_ci	brelse(bh);
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	return 0;
44962306a36Sopenharmony_ci}
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci/*
45362306a36Sopenharmony_ci *	readSuper()
45462306a36Sopenharmony_ci *
45562306a36Sopenharmony_ci * read superblock by raw sector address
45662306a36Sopenharmony_ci */
45762306a36Sopenharmony_ciint readSuper(struct super_block *sb, struct buffer_head **bpp)
45862306a36Sopenharmony_ci{
45962306a36Sopenharmony_ci	/* read in primary superblock */
46062306a36Sopenharmony_ci	*bpp = sb_bread(sb, SUPER1_OFF >> sb->s_blocksize_bits);
46162306a36Sopenharmony_ci	if (*bpp)
46262306a36Sopenharmony_ci		return 0;
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	/* read in secondary/replicated superblock */
46562306a36Sopenharmony_ci	*bpp = sb_bread(sb, SUPER2_OFF >> sb->s_blocksize_bits);
46662306a36Sopenharmony_ci	if (*bpp)
46762306a36Sopenharmony_ci		return 0;
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	return -EIO;
47062306a36Sopenharmony_ci}
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci/*
47462306a36Sopenharmony_ci *	logMOUNT()
47562306a36Sopenharmony_ci *
47662306a36Sopenharmony_ci * function: write a MOUNT log record for file system.
47762306a36Sopenharmony_ci *
47862306a36Sopenharmony_ci * MOUNT record keeps logredo() from processing log records
47962306a36Sopenharmony_ci * for this file system past this point in log.
48062306a36Sopenharmony_ci * it is harmless if mount fails.
48162306a36Sopenharmony_ci *
48262306a36Sopenharmony_ci * note: MOUNT record is at aggregate level, not at fileset level,
48362306a36Sopenharmony_ci * since log records of previous mounts of a fileset
48462306a36Sopenharmony_ci * (e.g., AFTER record of extent allocation) have to be processed
48562306a36Sopenharmony_ci * to update block allocation map at aggregate level.
48662306a36Sopenharmony_ci */
48762306a36Sopenharmony_cistatic int logMOUNT(struct super_block *sb)
48862306a36Sopenharmony_ci{
48962306a36Sopenharmony_ci	struct jfs_log *log = JFS_SBI(sb)->log;
49062306a36Sopenharmony_ci	struct lrd lrd;
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	lrd.logtid = 0;
49362306a36Sopenharmony_ci	lrd.backchain = 0;
49462306a36Sopenharmony_ci	lrd.type = cpu_to_le16(LOG_MOUNT);
49562306a36Sopenharmony_ci	lrd.length = 0;
49662306a36Sopenharmony_ci	lrd.aggregate = cpu_to_le32(new_encode_dev(sb->s_bdev->bd_dev));
49762306a36Sopenharmony_ci	lmLog(log, NULL, &lrd, NULL);
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	return 0;
50062306a36Sopenharmony_ci}
501